cgai386.pas 152 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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. }
  18. unit cgai386;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. cobjects,
  23. {$ifndef CG11}
  24. tree,
  25. {$endif}
  26. cpubase,cpuasm,
  27. symconst,symtable,aasm;
  28. {$define TESTGETTEMP to store const that
  29. are written into temps for later release PM }
  30. function def_opsize(p1:pdef):topsize;
  31. function def2def_opsize(p1,p2:pdef):topsize;
  32. function def_getreg(p1:pdef):tregister;
  33. function makereg8(r:tregister):tregister;
  34. function makereg16(r:tregister):tregister;
  35. function makereg32(r:tregister):tregister;
  36. procedure locflags2reg(var l:tlocation;opsize:topsize);
  37. procedure locjump2reg(var l:tlocation;opsize:topsize; otl, ofl: pasmlabel);
  38. procedure emitlab(var l : pasmlabel);
  39. procedure emitjmp(c : tasmcond;var l : pasmlabel);
  40. procedure emit_flag2reg(flag:tresflags;hregister:tregister);
  41. procedure emit_none(i : tasmop;s : topsize);
  42. procedure emit_const(i : tasmop;s : topsize;c : longint);
  43. procedure emit_reg(i : tasmop;s : topsize;reg : tregister);
  44. procedure emit_ref(i : tasmop;s : topsize;ref : preference);
  45. procedure emit_const_reg(i : tasmop;s : topsize;c : longint;reg : tregister);
  46. procedure emit_const_ref(i : tasmop;s : topsize;c : longint;ref : preference);
  47. procedure emit_ref_reg(i : tasmop;s : topsize;ref : preference;reg : tregister);
  48. procedure emit_reg_ref(i : tasmop;s : topsize;reg : tregister;ref : preference);
  49. procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
  50. procedure emit_const_reg_reg(i : tasmop;s : topsize;c : longint;reg1,reg2 : tregister);
  51. procedure emit_reg_reg_reg(i : tasmop;s : topsize;reg1,reg2,reg3 : tregister);
  52. procedure emit_sym(i : tasmop;s : topsize;op : pasmsymbol);
  53. procedure emit_sym_ofs(i : tasmop;s : topsize;op : pasmsymbol;ofs : longint);
  54. procedure emit_sym_ofs_reg(i : tasmop;s : topsize;op : pasmsymbol;ofs:longint;reg : tregister);
  55. procedure emit_sym_ofs_ref(i : tasmop;s : topsize;op : pasmsymbol;ofs:longint;ref : preference);
  56. procedure emitcall(const routine:string);
  57. procedure emit_mov_loc_ref(const t:tlocation;const ref:treference;siz:topsize;freetemp:boolean);
  58. procedure emit_mov_loc_reg(const t:tlocation;reg:tregister);
  59. procedure emit_mov_ref_reg64(r : treference;rl,rh : tregister);
  60. procedure emit_lea_loc_ref(const t:tlocation;const ref:treference;freetemp:boolean);
  61. procedure emit_lea_loc_reg(const t:tlocation;reg:tregister;freetemp:boolean);
  62. procedure emit_push_loc(const t:tlocation);
  63. procedure emit_push_mem_size(const t: treference; size: longint);
  64. { pushes qword location to the stack }
  65. procedure emit_pushq_loc(const t : tlocation);
  66. procedure release_qword_loc(const t : tlocation);
  67. { remove non regvar registers in loc from regs (in the format }
  68. { pushusedregisters uses) }
  69. procedure remove_non_regvars_from_loc(const t: tlocation; var regs: byte);
  70. { releases the registers of a location }
  71. procedure release_loc(const t : tlocation);
  72. procedure emit_pushw_loc(const t:tlocation);
  73. procedure emit_push_lea_loc(const t:tlocation;freetemp:boolean);
  74. procedure emit_to_mem(var t:tlocation;def:pdef);
  75. procedure emit_to_reg16(var hr:tregister);
  76. procedure emit_to_reg32(var hr:tregister);
  77. procedure emit_mov_reg_loc(reg: TRegister; const t:tlocation);
  78. procedure emit_movq_reg_loc(reghigh,reglow: TRegister;t:tlocation);
  79. procedure copyshortstring(const dref,sref : treference;len : byte;
  80. loadref, del_sref: boolean);
  81. procedure finalize(t : pdef;const ref : treference;is_already_ref : boolean);
  82. procedure incrstringref(t : pdef;const ref : treference);
  83. procedure decrstringref(t : pdef;const ref : treference);
  84. procedure push_int(l : longint);
  85. procedure emit_push_mem(const ref : treference);
  86. procedure emitpushreferenceaddr(const ref : treference);
  87. {$ifndef CG11}
  88. function maybe_push(needed : byte;p : {$ifdef CG11}tnode{$else}ptree{$endif};isint64 : boolean) : boolean;
  89. procedure pushsetelement(p : {$ifdef CG11}tnode{$else}ptree{$endif});
  90. procedure restore(p : {$ifdef CG11}tnode{$else}ptree{$endif};isint64 : boolean);
  91. procedure push_value_para(p:{$ifdef CG11}tnode{$else}ptree{$endif};inlined,is_cdecl:boolean;
  92. para_offset:longint;alignment : longint);
  93. {$ifdef TEMPS_NOT_PUSH}
  94. { does the same as restore, but uses temp. space instead of pushing }
  95. function maybe_push(needed : byte;p : ptree;isint64 : boolean) : boolean;
  96. procedure restorefromtemp(p : ptree;isint64 : boolean);
  97. {$endif TEMPS_NOT_PUSH}
  98. {$endif}
  99. procedure floatload(t : tfloattype;const ref : treference);
  100. procedure floatstore(t : tfloattype;const ref : treference);
  101. procedure floatloadops(t : tfloattype;var op : tasmop;var s : topsize);
  102. procedure floatstoreops(t : tfloattype;var op : tasmop;var s : topsize);
  103. procedure maybe_loadesi;
  104. procedure emitloadord2reg(const location:Tlocation;orddef:Porddef;destreg:Tregister;delloc:boolean);
  105. procedure concatcopy(source,dest : treference;size : longint;delsource : boolean;loadref:boolean);
  106. {$ifndef CG11}
  107. procedure maketojumpbool(p : ptree);
  108. procedure emitoverflowcheck(p:ptree);
  109. procedure emitrangecheck(p:ptree;todef:pdef);
  110. procedure firstcomplex(p : ptree);
  111. {$endif}
  112. procedure genentrycode(alist : paasmoutput;const proc_names:Tstringcontainer;make_global:boolean;
  113. stackframe:longint;
  114. var parasize:longint;var nostackframe:boolean;
  115. inlined : boolean);
  116. procedure genexitcode(alist : paasmoutput;parasize:longint;
  117. nostackframe,inlined:boolean);
  118. { if a unit doesn't have a explicit init/final code, }
  119. { we've to generate one, if the units has ansistrings }
  120. { in the interface or implementation }
  121. procedure genimplicitunitfinal(alist : paasmoutput);
  122. procedure genimplicitunitinit(alist : paasmoutput);
  123. {$ifdef test_dest_loc}
  124. const
  125. { used to avoid temporary assignments }
  126. dest_loc_known : boolean = false;
  127. in_dest_loc : boolean = false;
  128. dest_loc_tree : ptree = nil;
  129. var
  130. dest_loc : tlocation;
  131. procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
  132. {$endif test_dest_loc}
  133. implementation
  134. uses
  135. {$ifdef delphi}
  136. sysutils,
  137. {$else}
  138. strings,
  139. {$endif}
  140. cutils,globtype,systems,globals,verbose,fmodule,types,
  141. tgeni386,temp_gen,hcodegen,regvars
  142. {$ifdef GDB}
  143. ,gdb
  144. {$endif}
  145. {$ifndef NOTARGETWIN32}
  146. ,t_win32
  147. {$endif}
  148. ;
  149. {*****************************************************************************
  150. Helpers
  151. *****************************************************************************}
  152. function def_opsize(p1:pdef):topsize;
  153. begin
  154. case p1^.size of
  155. 1 : def_opsize:=S_B;
  156. 2 : def_opsize:=S_W;
  157. 4 : def_opsize:=S_L;
  158. else
  159. internalerror(130820001);
  160. end;
  161. end;
  162. function def2def_opsize(p1,p2:pdef):topsize;
  163. var
  164. o1 : topsize;
  165. begin
  166. case p1^.size of
  167. 1 : o1:=S_B;
  168. 2 : o1:=S_W;
  169. 4 : o1:=S_L;
  170. { I don't know if we need it (FK) }
  171. 8 : o1:=S_L;
  172. else
  173. internalerror(130820002);
  174. end;
  175. if assigned(p2) then
  176. begin
  177. case p2^.size of
  178. 1 : o1:=S_B;
  179. 2 : begin
  180. if o1=S_B then
  181. o1:=S_BW
  182. else
  183. o1:=S_W;
  184. end;
  185. 4,8:
  186. begin
  187. case o1 of
  188. S_B : o1:=S_BL;
  189. S_W : o1:=S_WL;
  190. end;
  191. end;
  192. end;
  193. end;
  194. def2def_opsize:=o1;
  195. end;
  196. function def_getreg(p1:pdef):tregister;
  197. begin
  198. case p1^.size of
  199. 1 : def_getreg:=reg32toreg8(getregister32);
  200. 2 : def_getreg:=reg32toreg16(getregister32);
  201. 4 : def_getreg:=getregister32;
  202. else
  203. internalerror(130820003);
  204. end;
  205. end;
  206. function makereg8(r:tregister):tregister;
  207. begin
  208. case r of
  209. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  210. makereg8:=reg32toreg8(r);
  211. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  212. makereg8:=reg16toreg8(r);
  213. R_AL,R_BL,R_CL,R_DL :
  214. makereg8:=r;
  215. end;
  216. end;
  217. function makereg16(r:tregister):tregister;
  218. begin
  219. case r of
  220. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  221. makereg16:=reg32toreg16(r);
  222. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  223. makereg16:=r;
  224. R_AL,R_BL,R_CL,R_DL :
  225. makereg16:=reg8toreg16(r);
  226. end;
  227. end;
  228. function makereg32(r:tregister):tregister;
  229. begin
  230. case r of
  231. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  232. makereg32:=r;
  233. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  234. makereg32:=reg16toreg32(r);
  235. R_AL,R_BL,R_CL,R_DL :
  236. makereg32:=reg8toreg32(r);
  237. end;
  238. end;
  239. procedure locflags2reg(var l:tlocation;opsize:topsize);
  240. var
  241. hregister : tregister;
  242. begin
  243. if (l.loc=LOC_FLAGS) then
  244. begin
  245. hregister:=getregister32;
  246. case opsize of
  247. S_W : hregister:=reg32toreg16(hregister);
  248. S_B : hregister:=reg32toreg8(hregister);
  249. end;
  250. emit_flag2reg(l.resflags,hregister);
  251. l.loc:=LOC_REGISTER;
  252. l.register:=hregister;
  253. end
  254. else internalerror(270720001);
  255. end;
  256. procedure locjump2reg(var l:tlocation;opsize:topsize; otl, ofl: pasmlabel);
  257. var
  258. hregister : tregister;
  259. hl : pasmlabel;
  260. begin
  261. if l.loc = LOC_JUMP then
  262. begin
  263. hregister:=getregister32;
  264. case opsize of
  265. S_W : hregister:=reg32toreg16(hregister);
  266. S_B : hregister:=reg32toreg8(hregister);
  267. end;
  268. l.loc:=LOC_REGISTER;
  269. l.register:=hregister;
  270. emitlab(truelabel);
  271. truelabel:=otl;
  272. emit_const_reg(A_MOV,opsize,1,hregister);
  273. getlabel(hl);
  274. emitjmp(C_None,hl);
  275. emitlab(falselabel);
  276. falselabel:=ofl;
  277. emit_reg_reg(A_XOR,S_L,makereg32(hregister),
  278. makereg32(hregister));
  279. emitlab(hl);
  280. end
  281. else internalerror(270720002);
  282. end;
  283. {*****************************************************************************
  284. Emit Assembler
  285. *****************************************************************************}
  286. procedure emitlab(var l : pasmlabel);
  287. begin
  288. if not l^.is_set then
  289. exprasmlist^.concat(new(pai_label,init(l)))
  290. else
  291. internalerror(7453984);
  292. end;
  293. procedure emitjmp(c : tasmcond;var l : pasmlabel);
  294. var
  295. ai : Paicpu;
  296. begin
  297. if c=C_None then
  298. ai := new(paicpu,op_sym(A_JMP,S_NO,l))
  299. else
  300. begin
  301. ai:=new(paicpu,op_sym(A_Jcc,S_NO,l));
  302. ai^.SetCondition(c);
  303. end;
  304. ai^.is_jmp:=true;
  305. exprasmlist^.concat(ai);
  306. end;
  307. procedure emit_flag2reg(flag:tresflags;hregister:tregister);
  308. var
  309. ai : paicpu;
  310. hreg : tregister;
  311. begin
  312. hreg:=makereg8(hregister);
  313. ai:=new(paicpu,op_reg(A_Setcc,S_B,hreg));
  314. ai^.SetCondition(flag_2_cond[flag]);
  315. exprasmlist^.concat(ai);
  316. if hreg<>hregister then
  317. begin
  318. if hregister in regset16bit then
  319. emit_to_reg16(hreg)
  320. else
  321. emit_to_reg32(hreg);
  322. end;
  323. end;
  324. procedure emit_none(i : tasmop;s : topsize);
  325. begin
  326. exprasmlist^.concat(new(paicpu,op_none(i,s)));
  327. end;
  328. procedure emit_reg(i : tasmop;s : topsize;reg : tregister);
  329. begin
  330. exprasmlist^.concat(new(paicpu,op_reg(i,s,reg)));
  331. end;
  332. procedure emit_ref(i : tasmop;s : topsize;ref : preference);
  333. begin
  334. exprasmlist^.concat(new(paicpu,op_ref(i,s,ref)));
  335. end;
  336. procedure emit_const(i : tasmop;s : topsize;c : longint);
  337. begin
  338. exprasmlist^.concat(new(paicpu,op_const(i,s,c)));
  339. end;
  340. procedure emit_const_reg(i : tasmop;s : topsize;c : longint;reg : tregister);
  341. begin
  342. exprasmlist^.concat(new(paicpu,op_const_reg(i,s,c,reg)));
  343. end;
  344. procedure emit_const_ref(i : tasmop;s : topsize;c : longint;ref : preference);
  345. begin
  346. exprasmlist^.concat(new(paicpu,op_const_ref(i,s,c,ref)));
  347. end;
  348. procedure emit_ref_reg(i : tasmop;s : topsize;ref : preference;reg : tregister);
  349. begin
  350. exprasmlist^.concat(new(paicpu,op_ref_reg(i,s,ref,reg)));
  351. end;
  352. procedure emit_reg_ref(i : tasmop;s : topsize;reg : tregister;ref : preference);
  353. begin
  354. exprasmlist^.concat(new(paicpu,op_reg_ref(i,s,reg,ref)));
  355. end;
  356. procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
  357. begin
  358. if (reg1<>reg2) or (i<>A_MOV) then
  359. exprasmlist^.concat(new(paicpu,op_reg_reg(i,s,reg1,reg2)));
  360. end;
  361. procedure emit_const_reg_reg(i : tasmop;s : topsize;c : longint;reg1,reg2 : tregister);
  362. begin
  363. exprasmlist^.concat(new(paicpu,op_const_reg_reg(i,s,c,reg1,reg2)));
  364. end;
  365. procedure emit_reg_reg_reg(i : tasmop;s : topsize;reg1,reg2,reg3 : tregister);
  366. begin
  367. exprasmlist^.concat(new(paicpu,op_reg_reg_reg(i,s,reg1,reg2,reg3)));
  368. end;
  369. procedure emit_sym(i : tasmop;s : topsize;op : pasmsymbol);
  370. begin
  371. exprasmlist^.concat(new(paicpu,op_sym(i,s,op)));
  372. end;
  373. procedure emit_sym_ofs(i : tasmop;s : topsize;op : pasmsymbol;ofs : longint);
  374. begin
  375. exprasmlist^.concat(new(paicpu,op_sym_ofs(i,s,op,ofs)));
  376. end;
  377. procedure emit_sym_ofs_reg(i : tasmop;s : topsize;op : pasmsymbol;ofs:longint;reg : tregister);
  378. begin
  379. exprasmlist^.concat(new(paicpu,op_sym_ofs_reg(i,s,op,ofs,reg)));
  380. end;
  381. procedure emit_sym_ofs_ref(i : tasmop;s : topsize;op : pasmsymbol;ofs:longint;ref : preference);
  382. begin
  383. exprasmlist^.concat(new(paicpu,op_sym_ofs_ref(i,s,op,ofs,ref)));
  384. end;
  385. procedure emitcall(const routine:string);
  386. begin
  387. exprasmlist^.concat(new(paicpu,op_sym(A_CALL,S_NO,newasmsymbol(routine))));
  388. end;
  389. { only usefull in startup code }
  390. procedure emitinsertcall(const routine:string);
  391. begin
  392. exprasmlist^.insert(new(paicpu,op_sym(A_CALL,S_NO,newasmsymbol(routine))));
  393. end;
  394. procedure emit_mov_loc_ref(const t:tlocation;const ref:treference;siz:topsize;freetemp:boolean);
  395. var
  396. hreg : tregister;
  397. pushedeax : boolean;
  398. begin
  399. pushedeax:=false;
  400. case t.loc of
  401. LOC_REGISTER,
  402. LOC_CREGISTER : begin
  403. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,siz,
  404. t.register,newreference(ref))));
  405. ungetregister32(t.register); { the register is not needed anymore }
  406. end;
  407. LOC_MEM,
  408. LOC_REFERENCE : begin
  409. if t.reference.is_immediate then
  410. emit_const_ref(A_MOV,siz,
  411. t.reference.offset,newreference(ref))
  412. else
  413. begin
  414. case siz of
  415. S_B : begin
  416. { we can't do a getregister in the code generator }
  417. { without problems!!! }
  418. if usablereg32>0 then
  419. hreg:=reg32toreg8(getregister32)
  420. else
  421. begin
  422. emit_reg(A_PUSH,S_L,R_EAX);
  423. pushedeax:=true;
  424. hreg:=R_AL;
  425. end;
  426. end;
  427. S_W : hreg:=R_DI;
  428. S_L : hreg:=R_EDI;
  429. end;
  430. if hreg in [R_DI,R_EDI] then
  431. getexplicitregister32(R_EDI);
  432. emit_ref_reg(A_MOV,siz,
  433. newreference(t.reference),hreg);
  434. del_reference(t.reference);
  435. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,siz,
  436. hreg,newreference(ref))));
  437. if siz=S_B then
  438. begin
  439. if pushedeax then
  440. emit_reg(A_POP,S_L,R_EAX)
  441. else
  442. ungetregister(hreg);
  443. end;
  444. if hreg in [R_DI,R_EDI] then
  445. ungetregister32(R_EDI);
  446. { we can release the registers }
  447. { but only AFTER the MOV! Important for the optimizer!
  448. (JM)}
  449. del_reference(ref);
  450. end;
  451. if freetemp then
  452. ungetiftemp(t.reference);
  453. end;
  454. else
  455. internalerror(330);
  456. end;
  457. end;
  458. procedure emit_mov_loc_reg(const t:tlocation;reg:tregister);
  459. begin
  460. case t.loc of
  461. LOC_REGISTER,
  462. LOC_CREGISTER : begin
  463. emit_reg_reg(A_MOV,S_L,t.register,reg);
  464. ungetregister32(t.register); { the register is not needed anymore }
  465. end;
  466. LOC_MEM,
  467. LOC_REFERENCE : begin
  468. if t.reference.is_immediate then
  469. emit_const_reg(A_MOV,S_L,
  470. t.reference.offset,reg)
  471. else
  472. begin
  473. emit_ref_reg(A_MOV,S_L,
  474. newreference(t.reference),reg);
  475. end;
  476. end;
  477. else
  478. internalerror(330);
  479. end;
  480. end;
  481. procedure emit_mov_reg_loc(reg: TRegister; const t:tlocation);
  482. begin
  483. case t.loc of
  484. LOC_REGISTER,
  485. LOC_CREGISTER : begin
  486. emit_reg_reg(A_MOV,RegSize(Reg),
  487. reg,t.register);
  488. end;
  489. LOC_MEM,
  490. LOC_REFERENCE : begin
  491. if t.reference.is_immediate then
  492. internalerror(334)
  493. else
  494. begin
  495. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,RegSize(Reg),
  496. Reg,newreference(t.reference))));
  497. end;
  498. end;
  499. else
  500. internalerror(330);
  501. end;
  502. end;
  503. procedure emit_lea_loc_reg(const t:tlocation;reg:tregister;freetemp:boolean);
  504. begin
  505. case t.loc of
  506. LOC_MEM,
  507. LOC_REFERENCE : begin
  508. if t.reference.is_immediate then
  509. internalerror(331)
  510. else
  511. begin
  512. emit_ref_reg(A_LEA,S_L,
  513. newreference(t.reference),reg);
  514. end;
  515. if freetemp then
  516. ungetiftemp(t.reference);
  517. end;
  518. else
  519. internalerror(332);
  520. end;
  521. end;
  522. procedure emit_movq_reg_loc(reghigh,reglow: TRegister;t:tlocation);
  523. begin
  524. case t.loc of
  525. LOC_REGISTER,
  526. LOC_CREGISTER : begin
  527. emit_reg_reg(A_MOV,S_L,
  528. reglow,t.registerlow);
  529. emit_reg_reg(A_MOV,S_L,
  530. reghigh,t.registerhigh);
  531. end;
  532. LOC_MEM,
  533. LOC_REFERENCE : begin
  534. if t.reference.is_immediate then
  535. internalerror(334)
  536. else
  537. begin
  538. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  539. Reglow,newreference(t.reference))));
  540. inc(t.reference.offset,4);
  541. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  542. Reghigh,newreference(t.reference))));
  543. end;
  544. end;
  545. else
  546. internalerror(330);
  547. end;
  548. end;
  549. procedure emit_pushq_loc(const t : tlocation);
  550. var
  551. hr : preference;
  552. begin
  553. case t.loc of
  554. LOC_REGISTER,
  555. LOC_CREGISTER:
  556. begin
  557. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,
  558. t.registerhigh)));
  559. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,
  560. t.registerlow)));
  561. end;
  562. LOC_MEM,
  563. LOC_REFERENCE:
  564. begin
  565. hr:=newreference(t.reference);
  566. inc(hr^.offset,4);
  567. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,
  568. hr)));
  569. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,
  570. newreference(t.reference))));
  571. ungetiftemp(t.reference);
  572. end;
  573. else internalerror(331);
  574. end;
  575. end;
  576. procedure remove_non_regvars_from_loc(const t: tlocation; var regs: byte);
  577. begin
  578. case t.loc of
  579. LOC_REGISTER:
  580. { can't be a regvar, since it would be LOC_CREGISTER then }
  581. regs := regs and not($80 shr byte(t.register));
  582. LOC_MEM,LOC_REFERENCE:
  583. begin
  584. if not(cs_regalloc in aktglobalswitches) or
  585. (t.reference.base in usableregs) then
  586. regs := regs and
  587. not($80 shr byte(t.reference.base));
  588. if not(cs_regalloc in aktglobalswitches) or
  589. (t.reference.index in usableregs) then
  590. regs := regs and
  591. not($80 shr byte(t.reference.index));
  592. end;
  593. end;
  594. end;
  595. procedure release_loc(const t : tlocation);
  596. begin
  597. case t.loc of
  598. LOC_REGISTER,
  599. LOC_CREGISTER:
  600. begin
  601. ungetregister32(t.register);
  602. end;
  603. LOC_MEM,
  604. LOC_REFERENCE:
  605. del_reference(t.reference);
  606. else internalerror(332);
  607. end;
  608. end;
  609. procedure release_qword_loc(const t : tlocation);
  610. begin
  611. case t.loc of
  612. LOC_REGISTER,
  613. LOC_CREGISTER:
  614. begin
  615. ungetregister32(t.registerhigh);
  616. ungetregister32(t.registerlow);
  617. end;
  618. LOC_MEM,
  619. LOC_REFERENCE:
  620. del_reference(t.reference);
  621. else internalerror(331);
  622. end;
  623. end;
  624. procedure emit_push_loc(const t:tlocation);
  625. begin
  626. case t.loc of
  627. LOC_REGISTER,
  628. LOC_CREGISTER : begin
  629. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,makereg32(t.register))));
  630. ungetregister(t.register); { the register is not needed anymore }
  631. end;
  632. LOC_MEM,
  633. LOC_REFERENCE : begin
  634. if t.reference.is_immediate then
  635. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,t.reference.offset)))
  636. else
  637. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,newreference(t.reference))));
  638. del_reference(t.reference);
  639. ungetiftemp(t.reference);
  640. end;
  641. else
  642. internalerror(330);
  643. end;
  644. end;
  645. procedure emit_pushw_loc(const t:tlocation);
  646. var
  647. opsize : topsize;
  648. begin
  649. case t.loc of
  650. LOC_REGISTER,
  651. LOC_CREGISTER : begin
  652. if target_os.stackalignment=4 then
  653. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,makereg32(t.register))))
  654. else
  655. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_W,makereg16(t.register))));
  656. ungetregister(t.register); { the register is not needed anymore }
  657. end;
  658. LOC_MEM,
  659. LOC_REFERENCE : begin
  660. if target_os.stackalignment=4 then
  661. opsize:=S_L
  662. else
  663. opsize:=S_W;
  664. if t.reference.is_immediate then
  665. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,opsize,t.reference.offset)))
  666. else
  667. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,opsize,newreference(t.reference))));
  668. del_reference(t.reference);
  669. ungetiftemp(t.reference);
  670. end;
  671. else
  672. internalerror(330);
  673. end;
  674. end;
  675. procedure emit_lea_loc_ref(const t:tlocation;const ref:treference;freetemp:boolean);
  676. begin
  677. case t.loc of
  678. LOC_MEM,
  679. LOC_REFERENCE : begin
  680. if t.reference.is_immediate then
  681. internalerror(331)
  682. else
  683. begin
  684. getexplicitregister32(R_EDI);
  685. emit_ref_reg(A_LEA,S_L,
  686. newreference(t.reference),R_EDI);
  687. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  688. R_EDI,newreference(ref))));
  689. ungetregister32(R_EDI);
  690. end;
  691. { release the registers }
  692. del_reference(t.reference);
  693. if freetemp then
  694. ungetiftemp(t.reference);
  695. end;
  696. else
  697. internalerror(332);
  698. end;
  699. end;
  700. procedure emit_push_lea_loc(const t:tlocation;freetemp:boolean);
  701. begin
  702. case t.loc of
  703. LOC_MEM,
  704. LOC_REFERENCE : begin
  705. if t.reference.is_immediate then
  706. internalerror(331)
  707. else
  708. begin
  709. getexplicitregister32(R_EDI);
  710. emit_ref_reg(A_LEA,S_L,
  711. newreference(t.reference),R_EDI);
  712. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  713. ungetregister32(R_EDI);
  714. end;
  715. if freetemp then
  716. ungetiftemp(t.reference);
  717. end;
  718. else
  719. internalerror(332);
  720. end;
  721. end;
  722. procedure emit_push_mem_size(const t: treference; size: longint);
  723. var
  724. s: topsize;
  725. begin
  726. if t.is_immediate then
  727. begin
  728. if (size=4) or
  729. (target_os.stackalignment=4) then
  730. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,t.offset)))
  731. else
  732. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_W,t.offset)));
  733. end
  734. else
  735. if size < 4 then
  736. begin
  737. getexplicitregister32(R_EDI);
  738. case size of
  739. 1: s := S_BL;
  740. 2: s := S_WL;
  741. else internalerror(200008071);
  742. end;
  743. exprasmlist^.concat(new(paicpu,op_ref_reg(A_MOVZX,s,
  744. newreference(t),R_EDI)));
  745. if target_os.stackalignment=4 then
  746. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)))
  747. else
  748. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_W,R_DI)));
  749. ungetregister32(R_EDI);
  750. end
  751. else
  752. if size = 4 then
  753. emit_push_mem(t)
  754. else
  755. internalerror(200008072);
  756. end;
  757. procedure emit_to_mem(var t:tlocation;def:pdef);
  758. var
  759. r : treference;
  760. begin
  761. case t.loc of
  762. LOC_FPU : begin
  763. reset_reference(t.reference);
  764. gettempofsizereference(10,t.reference);
  765. floatstore(pfloatdef(def)^.typ,t.reference);
  766. end;
  767. LOC_REGISTER:
  768. begin
  769. if is_64bitint(def) then
  770. begin
  771. gettempofsizereference(8,r);
  772. emit_reg_ref(A_MOV,S_L,t.registerlow,newreference(r));
  773. inc(r.offset,4);
  774. emit_reg_ref(A_MOV,S_L,t.registerhigh,newreference(r));
  775. dec(r.offset,4);
  776. t.reference:=r;
  777. end
  778. else
  779. internalerror(1405001);
  780. end;
  781. LOC_MEM,
  782. LOC_REFERENCE : ;
  783. LOC_CFPUREGISTER : begin
  784. emit_reg(A_FLD,S_NO,correct_fpuregister(t.register,fpuvaroffset));
  785. inc(fpuvaroffset);
  786. reset_reference(t.reference);
  787. gettempofsizereference(10,t.reference);
  788. floatstore(pfloatdef(def)^.typ,t.reference);
  789. end;
  790. else
  791. internalerror(333);
  792. end;
  793. t.loc:=LOC_MEM;
  794. end;
  795. procedure emit_to_reg16(var hr:tregister);
  796. begin
  797. { ranges are a little bit bug sensitive ! }
  798. case hr of
  799. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP,R_EBP:
  800. begin
  801. hr:=reg32toreg16(hr);
  802. end;
  803. R_AL,R_BL,R_CL,R_DL:
  804. begin
  805. hr:=reg8toreg16(hr);
  806. emit_const_reg(A_AND,S_W,$ff,hr);
  807. end;
  808. R_AH,R_BH,R_CH,R_DH:
  809. begin
  810. hr:=reg8toreg16(hr);
  811. emit_const_reg(A_AND,S_W,$ff00,hr);
  812. end;
  813. end;
  814. end;
  815. procedure emit_to_reg32(var hr:tregister);
  816. begin
  817. { ranges are a little bit bug sensitive ! }
  818. case hr of
  819. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP,R_BP:
  820. begin
  821. hr:=reg16toreg32(hr);
  822. emit_const_reg(A_AND,S_L,$ffff,hr);
  823. end;
  824. R_AL,R_BL,R_CL,R_DL:
  825. begin
  826. hr:=reg8toreg32(hr);
  827. emit_const_reg(A_AND,S_L,$ff,hr);
  828. end;
  829. R_AH,R_BH,R_CH,R_DH:
  830. begin
  831. hr:=reg8toreg32(hr);
  832. emit_const_reg(A_AND,S_L,$ff00,hr);
  833. end;
  834. end;
  835. end;
  836. procedure emit_mov_ref_reg64(r : treference;rl,rh : tregister);
  837. var
  838. hr : preference;
  839. begin
  840. { if we load a 64 bit reference, we must be careful because }
  841. { we could overwrite the registers of the reference by }
  842. { accident }
  843. getexplicitregister32(R_EDI);
  844. if r.base=rl then
  845. begin
  846. emit_reg_reg(A_MOV,S_L,r.base,
  847. R_EDI);
  848. r.base:=R_EDI;
  849. end
  850. else if r.index=rl then
  851. begin
  852. emit_reg_reg(A_MOV,S_L,r.index,
  853. R_EDI);
  854. r.index:=R_EDI;
  855. end;
  856. emit_ref_reg(A_MOV,S_L,
  857. newreference(r),rl);
  858. hr:=newreference(r);
  859. inc(hr^.offset,4);
  860. emit_ref_reg(A_MOV,S_L,
  861. hr,rh);
  862. ungetregister32(R_EDI);
  863. end;
  864. {*****************************************************************************
  865. Emit String Functions
  866. *****************************************************************************}
  867. procedure copyshortstring(const dref,sref : treference;len : byte;
  868. loadref, del_sref: boolean);
  869. begin
  870. emitpushreferenceaddr(dref);
  871. { if it's deleted right before it's used, the optimizer can move }
  872. { the reg deallocations to the right places (JM) }
  873. if del_sref then
  874. del_reference(sref);
  875. if loadref then
  876. emit_push_mem(sref)
  877. else
  878. emitpushreferenceaddr(sref);
  879. push_int(len);
  880. emitcall('FPC_SHORTSTR_COPY');
  881. maybe_loadesi;
  882. end;
  883. procedure copylongstring(const dref,sref : treference;len : longint;loadref:boolean);
  884. begin
  885. emitpushreferenceaddr(dref);
  886. if loadref then
  887. emit_push_mem(sref)
  888. else
  889. emitpushreferenceaddr(sref);
  890. push_int(len);
  891. emitcall('FPC_LONGSTR_COPY');
  892. maybe_loadesi;
  893. end;
  894. procedure incrstringref(t : pdef;const ref : treference);
  895. var
  896. pushedregs : tpushed;
  897. begin
  898. pushusedregisters(pushedregs,$ff);
  899. emitpushreferenceaddr(ref);
  900. if is_ansistring(t) then
  901. begin
  902. emitcall('FPC_ANSISTR_INCR_REF');
  903. end
  904. else if is_widestring(t) then
  905. begin
  906. emitcall('FPC_WIDESTR_INCR_REF');
  907. end
  908. else internalerror(1859);
  909. popusedregisters(pushedregs);
  910. end;
  911. procedure decrstringref(t : pdef;const ref : treference);
  912. var
  913. pushedregs : tpushed;
  914. begin
  915. pushusedregisters(pushedregs,$ff);
  916. emitpushreferenceaddr(ref);
  917. if is_ansistring(t) then
  918. begin
  919. emitcall('FPC_ANSISTR_DECR_REF');
  920. end
  921. else if is_widestring(t) then
  922. begin
  923. emitcall('FPC_WIDESTR_DECR_REF');
  924. end
  925. else internalerror(1859);
  926. popusedregisters(pushedregs);
  927. end;
  928. {*****************************************************************************
  929. Emit Push Functions
  930. *****************************************************************************}
  931. {$ifndef CG11}
  932. function maybe_push(needed : byte;p : ptree;isint64 : boolean) : boolean;
  933. var
  934. pushed : boolean;
  935. {hregister : tregister; }
  936. {$ifdef TEMPS_NOT_PUSH}
  937. href : treference;
  938. {$endif TEMPS_NOT_PUSH}
  939. begin
  940. if needed>usablereg32 then
  941. begin
  942. if (p^.location.loc=LOC_REGISTER) then
  943. begin
  944. if isint64 then
  945. begin
  946. {$ifdef TEMPS_NOT_PUSH}
  947. gettempofsizereference(href,8);
  948. p^.temp_offset:=href.offset;
  949. href.offset:=href.offset+4;
  950. exprasmlist^.concat(new(paicpu,op_reg(A_MOV,S_L,p^.location.registerhigh,href)));
  951. href.offset:=href.offset-4;
  952. {$else TEMPS_NOT_PUSH}
  953. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p^.location.registerhigh)));
  954. {$endif TEMPS_NOT_PUSH}
  955. ungetregister32(p^.location.registerhigh);
  956. end
  957. {$ifdef TEMPS_NOT_PUSH}
  958. else
  959. begin
  960. gettempofsizereference(href,4);
  961. p^.temp_offset:=href.offset;
  962. end
  963. {$endif TEMPS_NOT_PUSH}
  964. ;
  965. pushed:=true;
  966. {$ifdef TEMPS_NOT_PUSH}
  967. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,p^.location.register,href)));
  968. {$else TEMPS_NOT_PUSH}
  969. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p^.location.register)));
  970. {$endif TEMPS_NOT_PUSH}
  971. ungetregister32(p^.location.register);
  972. end
  973. else if (p^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  974. ((p^.location.reference.base<>R_NO) or
  975. (p^.location.reference.index<>R_NO)
  976. ) then
  977. begin
  978. del_reference(p^.location.reference);
  979. getexplicitregister32(R_EDI);
  980. emit_ref_reg(A_LEA,S_L,newreference(p^.location.reference),
  981. R_EDI);
  982. {$ifdef TEMPS_NOT_PUSH}
  983. gettempofsizereference(href,4);
  984. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,href)));
  985. p^.temp_offset:=href.offset;
  986. {$else TEMPS_NOT_PUSH}
  987. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  988. {$endif TEMPS_NOT_PUSH}
  989. ungetregister32(R_EDI);
  990. pushed:=true;
  991. end
  992. else pushed:=false;
  993. end
  994. else pushed:=false;
  995. maybe_push:=pushed;
  996. end;
  997. {$ifdef TEMPS_NOT_PUSH}
  998. function maybe_savetotemp(needed : byte;p : ptree;isint64 : boolean) : boolean;
  999. var
  1000. pushed : boolean;
  1001. href : treference;
  1002. begin
  1003. if needed>usablereg32 then
  1004. begin
  1005. if (p^.location.loc=LOC_REGISTER) then
  1006. begin
  1007. if isint64(p^.resulttype) then
  1008. begin
  1009. gettempofsizereference(href,8);
  1010. p^.temp_offset:=href.offset;
  1011. href.offset:=href.offset+4;
  1012. exprasmlist^.concat(new(paicpu,op_reg(A_MOV,S_L,p^.location.registerhigh,href)));
  1013. href.offset:=href.offset-4;
  1014. ungetregister32(p^.location.registerhigh);
  1015. end
  1016. else
  1017. begin
  1018. gettempofsizereference(href,4);
  1019. p^.temp_offset:=href.offset;
  1020. end;
  1021. pushed:=true;
  1022. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,p^.location.register,href)));
  1023. ungetregister32(p^.location.register);
  1024. end
  1025. else if (p^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  1026. ((p^.location.reference.base<>R_NO) or
  1027. (p^.location.reference.index<>R_NO)
  1028. ) then
  1029. begin
  1030. del_reference(p^.location.reference);
  1031. getexplicitregister32(R_EDI);
  1032. emit_ref_reg(A_LEA,S_L,newreference(p^.location.reference),
  1033. R_EDI);
  1034. gettempofsizereference(href,4);
  1035. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,href)));
  1036. ungetregister32(R_EDI);
  1037. p^.temp_offset:=href.offset;
  1038. pushed:=true;
  1039. end
  1040. else pushed:=false;
  1041. end
  1042. else pushed:=false;
  1043. maybe_push:=pushed;
  1044. end;
  1045. {$endif TEMPS_NOT_PUSH}
  1046. {$endif CG11}
  1047. procedure push_int(l : longint);
  1048. begin
  1049. if (l = 0) and
  1050. not(aktoptprocessor in [Class386, ClassP6]) and
  1051. not(cs_littlesize in aktglobalswitches)
  1052. Then
  1053. begin
  1054. getexplicitregister32(R_EDI);
  1055. emit_reg_reg(A_XOR,S_L,R_EDI,R_EDI);
  1056. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  1057. ungetregister32(R_EDI);
  1058. end
  1059. else
  1060. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,l)));
  1061. end;
  1062. procedure emit_push_mem(const ref : treference);
  1063. begin
  1064. if ref.is_immediate then
  1065. push_int(ref.offset)
  1066. else
  1067. begin
  1068. if not(aktoptprocessor in [Class386, ClassP6]) and
  1069. not(cs_littlesize in aktglobalswitches)
  1070. then
  1071. begin
  1072. getexplicitregister32(R_EDI);
  1073. emit_ref_reg(A_MOV,S_L,newreference(ref),R_EDI);
  1074. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  1075. ungetregister32(R_EDI);
  1076. end
  1077. else exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,newreference(ref))));
  1078. end;
  1079. end;
  1080. procedure emitpushreferenceaddr(const ref : treference);
  1081. var
  1082. href : treference;
  1083. begin
  1084. { this will fail for references to other segments !!! }
  1085. if ref.is_immediate then
  1086. { is this right ? }
  1087. begin
  1088. { push_int(ref.offset)}
  1089. gettempofsizereference(4,href);
  1090. emit_const_ref(A_MOV,S_L,ref.offset,newreference(href));
  1091. emitpushreferenceaddr(href);
  1092. del_reference(href);
  1093. end
  1094. else
  1095. begin
  1096. if ref.segment<>R_NO then
  1097. CGMessage(cg_e_cant_use_far_pointer_there);
  1098. if (ref.base=R_NO) and (ref.index=R_NO) then
  1099. exprasmlist^.concat(new(paicpu,op_sym_ofs(A_PUSH,S_L,ref.symbol,ref.offset)))
  1100. else if (ref.base=R_NO) and (ref.index<>R_NO) and
  1101. (ref.offset=0) and (ref.scalefactor=0) and (ref.symbol=nil) then
  1102. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,ref.index)))
  1103. else if (ref.base<>R_NO) and (ref.index=R_NO) and
  1104. (ref.offset=0) and (ref.symbol=nil) then
  1105. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,ref.base)))
  1106. else
  1107. begin
  1108. getexplicitregister32(R_EDI);
  1109. emit_ref_reg(A_LEA,S_L,newreference(ref),R_EDI);
  1110. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  1111. ungetregister32(R_EDI);
  1112. end;
  1113. end;
  1114. end;
  1115. {$ifndef CG11}
  1116. procedure pushsetelement(p : ptree);
  1117. {
  1118. copies p a set element on the stack
  1119. }
  1120. var
  1121. hr,hr16,hr32 : tregister;
  1122. begin
  1123. { copy the element on the stack, slightly complicated }
  1124. if p^.treetype=ordconstn then
  1125. begin
  1126. if target_os.stackalignment=4 then
  1127. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,p^.value)))
  1128. else
  1129. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_W,p^.value)));
  1130. end
  1131. else
  1132. begin
  1133. case p^.location.loc of
  1134. LOC_REGISTER,
  1135. LOC_CREGISTER :
  1136. begin
  1137. hr:=p^.location.register;
  1138. case hr of
  1139. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  1140. begin
  1141. hr16:=reg32toreg16(hr);
  1142. hr32:=hr;
  1143. end;
  1144. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  1145. begin
  1146. hr16:=hr;
  1147. hr32:=reg16toreg32(hr);
  1148. end;
  1149. R_AL,R_BL,R_CL,R_DL :
  1150. begin
  1151. hr16:=reg8toreg16(hr);
  1152. hr32:=reg8toreg32(hr);
  1153. end;
  1154. end;
  1155. if target_os.stackalignment=4 then
  1156. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,hr32)))
  1157. else
  1158. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_W,hr16)));
  1159. ungetregister32(hr32);
  1160. end;
  1161. else
  1162. begin
  1163. { you can't push more bytes than the size of the element, }
  1164. { because this may cross a page boundary and you'll get a }
  1165. { sigsegv (JM) }
  1166. emit_push_mem_size(p^.location.reference,1);
  1167. del_reference(p^.location.reference);
  1168. end;
  1169. end;
  1170. end;
  1171. end;
  1172. {$endif CG11}
  1173. {$ifndef CG11}
  1174. procedure restore(p : ptree;isint64 : boolean);
  1175. var
  1176. hregister : tregister;
  1177. {$ifdef TEMPS_NOT_PUSH}
  1178. href : treference;
  1179. {$endif TEMPS_NOT_PUSH}
  1180. begin
  1181. hregister:=getregister32;
  1182. {$ifdef TEMPS_NOT_PUSH}
  1183. reset_reference(href);
  1184. href.base:=procinfo^.frame_pointer;
  1185. href.offset:=p^.temp_offset;
  1186. emit_ref_reg(A_MOV,S_L,href,hregister);
  1187. {$else TEMPS_NOT_PUSH}
  1188. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,hregister)));
  1189. {$endif TEMPS_NOT_PUSH}
  1190. if (p^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  1191. begin
  1192. p^.location.register:=hregister;
  1193. if isint64 then
  1194. begin
  1195. p^.location.registerhigh:=getregister32;
  1196. {$ifdef TEMPS_NOT_PUSH}
  1197. href.offset:=p^.temp_offset+4;
  1198. emit_ref_reg(A_MOV,S_L,p^.location.registerhigh);
  1199. { set correctly for release ! }
  1200. href.offset:=p^.temp_offset;
  1201. {$else TEMPS_NOT_PUSH}
  1202. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,p^.location.registerhigh)));
  1203. {$endif TEMPS_NOT_PUSH}
  1204. end;
  1205. end
  1206. else
  1207. begin
  1208. reset_reference(p^.location.reference);
  1209. { any reasons why this was moved into the index register ? }
  1210. { normally usage of base register is much better (FK) }
  1211. p^.location.reference.base:=hregister;
  1212. { Why is this done? We can never be sure about p^.left
  1213. because otherwise secondload fails !!!
  1214. set_location(p^.left^.location,p^.location);}
  1215. end;
  1216. {$ifdef TEMPS_NOT_PUSH}
  1217. ungetiftemp(href);
  1218. {$endif TEMPS_NOT_PUSH}
  1219. end;
  1220. {$endif CG11}
  1221. {$ifdef TEMPS_NOT_PUSH}
  1222. procedure restorefromtemp(p : ptree;isint64 : boolean);
  1223. var
  1224. hregister : tregister;
  1225. href : treference;
  1226. begin
  1227. hregister:=getregister32;
  1228. reset_reference(href);
  1229. href.base:=procinfo^.frame_pointer;
  1230. href.offset:=p^.temp_offset;
  1231. emit_ref_reg(A_MOV,S_L,href,hregister);
  1232. if (p^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  1233. begin
  1234. p^.location.register:=hregister;
  1235. if isint64 then
  1236. begin
  1237. p^.location.registerhigh:=getregister32;
  1238. href.offset:=p^.temp_offset+4;
  1239. emit_ref_reg(A_MOV,S_L,p^.location.registerhigh);
  1240. { set correctly for release ! }
  1241. href.offset:=p^.temp_offset;
  1242. end;
  1243. end
  1244. else
  1245. begin
  1246. reset_reference(p^.location.reference);
  1247. p^.location.reference.base:=hregister;
  1248. { Why is this done? We can never be sure about p^.left
  1249. because otherwise secondload fails PM
  1250. set_location(p^.left^.location,p^.location);}
  1251. end;
  1252. ungetiftemp(href);
  1253. end;
  1254. {$endif TEMPS_NOT_PUSH}
  1255. {$ifndef CG11}
  1256. procedure push_value_para(p:ptree;inlined,is_cdecl:boolean;
  1257. para_offset:longint;alignment : longint);
  1258. var
  1259. tempreference : treference;
  1260. r : preference;
  1261. opsize : topsize;
  1262. op : tasmop;
  1263. hreg : tregister;
  1264. size : longint;
  1265. hlabel : pasmlabel;
  1266. begin
  1267. case p^.location.loc of
  1268. LOC_REGISTER,
  1269. LOC_CREGISTER:
  1270. begin
  1271. case p^.location.register of
  1272. R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,
  1273. R_EDI,R_ESP,R_EBP :
  1274. begin
  1275. if p^.resulttype^.size=8 then
  1276. begin
  1277. inc(pushedparasize,8);
  1278. if inlined then
  1279. begin
  1280. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1281. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  1282. p^.location.registerlow,r)));
  1283. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize+4);
  1284. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  1285. p^.location.registerhigh,r)));
  1286. end
  1287. else
  1288. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p^.location.registerhigh)));
  1289. ungetregister32(p^.location.registerhigh);
  1290. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p^.location.registerlow)));
  1291. ungetregister32(p^.location.registerlow);
  1292. end
  1293. else
  1294. begin
  1295. inc(pushedparasize,4);
  1296. if inlined then
  1297. begin
  1298. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1299. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  1300. p^.location.register,r)));
  1301. end
  1302. else
  1303. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,p^.location.register)));
  1304. ungetregister32(p^.location.register);
  1305. end;
  1306. end;
  1307. R_AX,R_BX,R_CX,R_DX,R_SI,R_DI:
  1308. begin
  1309. if alignment=4 then
  1310. begin
  1311. opsize:=S_L;
  1312. hreg:=reg16toreg32(p^.location.register);
  1313. inc(pushedparasize,4);
  1314. end
  1315. else
  1316. begin
  1317. opsize:=S_W;
  1318. hreg:=p^.location.register;
  1319. inc(pushedparasize,2);
  1320. end;
  1321. if inlined then
  1322. begin
  1323. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1324. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
  1325. end
  1326. else
  1327. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,opsize,hreg)));
  1328. ungetregister32(reg16toreg32(p^.location.register));
  1329. end;
  1330. R_AL,R_BL,R_CL,R_DL:
  1331. begin
  1332. if alignment=4 then
  1333. begin
  1334. opsize:=S_L;
  1335. hreg:=reg8toreg32(p^.location.register);
  1336. inc(pushedparasize,4);
  1337. end
  1338. else
  1339. begin
  1340. opsize:=S_W;
  1341. hreg:=reg8toreg16(p^.location.register);
  1342. inc(pushedparasize,2);
  1343. end;
  1344. { we must push always 16 bit }
  1345. if inlined then
  1346. begin
  1347. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1348. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
  1349. end
  1350. else
  1351. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,opsize,hreg)));
  1352. ungetregister32(reg8toreg32(p^.location.register));
  1353. end;
  1354. else internalerror(1899);
  1355. end;
  1356. end;
  1357. LOC_FPU:
  1358. begin
  1359. size:=align(pfloatdef(p^.resulttype)^.size,alignment);
  1360. inc(pushedparasize,size);
  1361. if not inlined then
  1362. emit_const_reg(A_SUB,S_L,size,R_ESP);
  1363. {$ifdef GDB}
  1364. if (cs_debuginfo in aktmoduleswitches) and
  1365. (exprasmlist^.first=exprasmlist^.last) then
  1366. exprasmlist^.concat(new(pai_force_line,init));
  1367. {$endif GDB}
  1368. r:=new_reference(R_ESP,0);
  1369. floatstoreops(pfloatdef(p^.resulttype)^.typ,op,opsize);
  1370. { this is the easiest case for inlined !! }
  1371. if inlined then
  1372. begin
  1373. r^.base:=procinfo^.framepointer;
  1374. r^.offset:=para_offset-pushedparasize;
  1375. end;
  1376. exprasmlist^.concat(new(paicpu,op_ref(op,opsize,r)));
  1377. dec(fpuvaroffset);
  1378. end;
  1379. LOC_CFPUREGISTER:
  1380. begin
  1381. exprasmlist^.concat(new(paicpu,op_reg(A_FLD,S_NO,
  1382. correct_fpuregister(p^.location.register,fpuvaroffset))));
  1383. size:=align(pfloatdef(p^.resulttype)^.size,alignment);
  1384. inc(pushedparasize,size);
  1385. if not inlined then
  1386. emit_const_reg(A_SUB,S_L,size,R_ESP);
  1387. {$ifdef GDB}
  1388. if (cs_debuginfo in aktmoduleswitches) and
  1389. (exprasmlist^.first=exprasmlist^.last) then
  1390. exprasmlist^.concat(new(pai_force_line,init));
  1391. {$endif GDB}
  1392. r:=new_reference(R_ESP,0);
  1393. floatstoreops(pfloatdef(p^.resulttype)^.typ,op,opsize);
  1394. { this is the easiest case for inlined !! }
  1395. if inlined then
  1396. begin
  1397. r^.base:=procinfo^.framepointer;
  1398. r^.offset:=para_offset-pushedparasize;
  1399. end;
  1400. exprasmlist^.concat(new(paicpu,op_ref(op,opsize,r)));
  1401. end;
  1402. LOC_REFERENCE,LOC_MEM:
  1403. begin
  1404. tempreference:=p^.location.reference;
  1405. del_reference(p^.location.reference);
  1406. case p^.resulttype^.deftype of
  1407. enumdef,
  1408. orddef :
  1409. begin
  1410. case p^.resulttype^.size of
  1411. 8 : begin
  1412. inc(pushedparasize,8);
  1413. if inlined then
  1414. begin
  1415. getexplicitregister32(R_EDI);
  1416. emit_ref_reg(A_MOV,S_L,
  1417. newreference(tempreference),R_EDI);
  1418. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1419. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1420. ungetregister32(R_EDI);
  1421. getexplicitregister32(R_EDI);
  1422. inc(tempreference.offset,4);
  1423. emit_ref_reg(A_MOV,S_L,
  1424. newreference(tempreference),R_EDI);
  1425. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize+4);
  1426. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1427. ungetregister32(R_EDI);
  1428. end
  1429. else
  1430. begin
  1431. inc(tempreference.offset,4);
  1432. emit_push_mem(tempreference);
  1433. dec(tempreference.offset,4);
  1434. emit_push_mem(tempreference);
  1435. end;
  1436. end;
  1437. 4 : begin
  1438. inc(pushedparasize,4);
  1439. if inlined then
  1440. begin
  1441. getexplicitregister32(R_EDI);
  1442. emit_ref_reg(A_MOV,S_L,
  1443. newreference(tempreference),R_EDI);
  1444. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1445. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1446. ungetregister32(R_EDI);
  1447. end
  1448. else
  1449. emit_push_mem(tempreference);
  1450. end;
  1451. 1,2 : begin
  1452. if alignment=4 then
  1453. begin
  1454. opsize:=S_L;
  1455. hreg:=R_EDI;
  1456. inc(pushedparasize,4);
  1457. end
  1458. else
  1459. begin
  1460. opsize:=S_W;
  1461. hreg:=R_DI;
  1462. inc(pushedparasize,2);
  1463. end;
  1464. if inlined then
  1465. begin
  1466. getexplicitregister32(R_EDI);
  1467. emit_ref_reg(A_MOV,opsize,
  1468. newreference(tempreference),hreg);
  1469. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1470. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
  1471. ungetregister32(R_EDI);
  1472. end
  1473. else
  1474. emit_push_mem_size(tempreference,p^.resulttype^.size);
  1475. end;
  1476. else
  1477. internalerror(234231);
  1478. end;
  1479. end;
  1480. floatdef :
  1481. begin
  1482. case pfloatdef(p^.resulttype)^.typ of
  1483. f32bit,
  1484. s32real :
  1485. begin
  1486. inc(pushedparasize,4);
  1487. if inlined then
  1488. begin
  1489. getexplicitregister32(R_EDI);
  1490. emit_ref_reg(A_MOV,S_L,
  1491. newreference(tempreference),R_EDI);
  1492. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1493. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1494. ungetregister32(R_EDI);
  1495. end
  1496. else
  1497. emit_push_mem(tempreference);
  1498. end;
  1499. s64real,
  1500. s64comp :
  1501. begin
  1502. inc(pushedparasize,4);
  1503. inc(tempreference.offset,4);
  1504. if inlined then
  1505. begin
  1506. getexplicitregister32(R_EDI);
  1507. emit_ref_reg(A_MOV,S_L,
  1508. newreference(tempreference),R_EDI);
  1509. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1510. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1511. ungetregister32(R_EDI);
  1512. end
  1513. else
  1514. emit_push_mem(tempreference);
  1515. inc(pushedparasize,4);
  1516. dec(tempreference.offset,4);
  1517. if inlined then
  1518. begin
  1519. getexplicitregister32(R_EDI);
  1520. emit_ref_reg(A_MOV,S_L,
  1521. newreference(tempreference),R_EDI);
  1522. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1523. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1524. ungetregister32(R_EDI);
  1525. end
  1526. else
  1527. emit_push_mem(tempreference);
  1528. end;
  1529. s80real :
  1530. begin
  1531. inc(pushedparasize,4);
  1532. if alignment=4 then
  1533. inc(tempreference.offset,8)
  1534. else
  1535. inc(tempreference.offset,6);
  1536. if inlined then
  1537. begin
  1538. getexplicitregister32(R_EDI);
  1539. emit_ref_reg(A_MOV,S_L,
  1540. newreference(tempreference),R_EDI);
  1541. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1542. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1543. ungetregister32(R_EDI);
  1544. end
  1545. else
  1546. emit_push_mem(tempreference);
  1547. dec(tempreference.offset,4);
  1548. inc(pushedparasize,4);
  1549. if inlined then
  1550. begin
  1551. getexplicitregister32(R_EDI);
  1552. emit_ref_reg(A_MOV,S_L,
  1553. newreference(tempreference),R_EDI);
  1554. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1555. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1556. ungetregister32(R_EDI);
  1557. end
  1558. else
  1559. emit_push_mem(tempreference);
  1560. if alignment=4 then
  1561. begin
  1562. opsize:=S_L;
  1563. hreg:=R_EDI;
  1564. inc(pushedparasize,4);
  1565. dec(tempreference.offset,4);
  1566. end
  1567. else
  1568. begin
  1569. opsize:=S_W;
  1570. hreg:=R_DI;
  1571. inc(pushedparasize,2);
  1572. dec(tempreference.offset,2);
  1573. end;
  1574. if inlined then
  1575. begin
  1576. getexplicitregister32(R_EDI);
  1577. emit_ref_reg(A_MOV,opsize,
  1578. newreference(tempreference),hreg);
  1579. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1580. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
  1581. ungetregister32(R_EDI);
  1582. end
  1583. else
  1584. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,opsize,
  1585. newreference(tempreference))));
  1586. end;
  1587. end;
  1588. end;
  1589. pointerdef,
  1590. procvardef,
  1591. classrefdef:
  1592. begin
  1593. inc(pushedparasize,4);
  1594. if inlined then
  1595. begin
  1596. getexplicitregister32(R_EDI);
  1597. emit_ref_reg(A_MOV,S_L,
  1598. newreference(tempreference),R_EDI);
  1599. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1600. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  1601. ungetregister32(R_EDI);
  1602. end
  1603. else
  1604. emit_push_mem(tempreference);
  1605. end;
  1606. arraydef,
  1607. recorddef,
  1608. stringdef,
  1609. setdef,
  1610. objectdef :
  1611. begin
  1612. { even some structured types are 32 bit }
  1613. if is_widestring(p^.resulttype) or
  1614. is_ansistring(p^.resulttype) or
  1615. is_smallset(p^.resulttype) or
  1616. ((p^.resulttype^.deftype in [recorddef,arraydef]) and
  1617. (
  1618. (p^.resulttype^.deftype<>arraydef) or not
  1619. (parraydef(p^.resulttype)^.IsConstructor or
  1620. parraydef(p^.resulttype)^.isArrayOfConst or
  1621. is_open_array(p^.resulttype))
  1622. ) and
  1623. (p^.resulttype^.size<=4)
  1624. ) or
  1625. ((p^.resulttype^.deftype=objectdef) and
  1626. pobjectdef(p^.resulttype)^.is_class) then
  1627. begin
  1628. if (p^.resulttype^.size>2) or
  1629. ((alignment=4) and (p^.resulttype^.size>0)) then
  1630. begin
  1631. inc(pushedparasize,4);
  1632. if inlined then
  1633. begin
  1634. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1635. concatcopy(tempreference,r^,4,false,false);
  1636. end
  1637. else
  1638. emit_push_mem(tempreference);
  1639. end
  1640. else
  1641. begin
  1642. if p^.resulttype^.size>0 then
  1643. begin
  1644. inc(pushedparasize,2);
  1645. if inlined then
  1646. begin
  1647. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1648. concatcopy(tempreference,r^,2,false,false);
  1649. end
  1650. else
  1651. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_W,newreference(tempreference))));
  1652. end;
  1653. end;
  1654. end
  1655. { call by value open array ? }
  1656. else if is_cdecl then
  1657. begin
  1658. { push on stack }
  1659. size:=align(p^.resulttype^.size,alignment);
  1660. inc(pushedparasize,size);
  1661. emit_const_reg(A_SUB,S_L,size,R_ESP);
  1662. r:=new_reference(R_ESP,0);
  1663. concatcopy(tempreference,r^,size,false,false);
  1664. end
  1665. else
  1666. internalerror(8954);
  1667. end;
  1668. else
  1669. CGMessage(cg_e_illegal_expression);
  1670. end;
  1671. end;
  1672. LOC_JUMP:
  1673. begin
  1674. getlabel(hlabel);
  1675. if alignment=4 then
  1676. begin
  1677. opsize:=S_L;
  1678. inc(pushedparasize,4);
  1679. end
  1680. else
  1681. begin
  1682. opsize:=S_W;
  1683. inc(pushedparasize,2);
  1684. end;
  1685. emitlab(truelabel);
  1686. if inlined then
  1687. begin
  1688. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1689. emit_const_ref(A_MOV,opsize,1,r);
  1690. end
  1691. else
  1692. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,opsize,1)));
  1693. emitjmp(C_None,hlabel);
  1694. emitlab(falselabel);
  1695. if inlined then
  1696. begin
  1697. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1698. emit_const_ref(A_MOV,opsize,0,r);
  1699. end
  1700. else
  1701. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,opsize,0)));
  1702. emitlab(hlabel);
  1703. end;
  1704. LOC_FLAGS:
  1705. begin
  1706. if not(R_EAX in unused) then
  1707. begin
  1708. getexplicitregister32(R_EDI);
  1709. emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
  1710. end;
  1711. emit_flag2reg(p^.location.resflags,R_AL);
  1712. emit_reg_reg(A_MOVZX,S_BW,R_AL,R_AX);
  1713. if alignment=4 then
  1714. begin
  1715. opsize:=S_L;
  1716. hreg:=R_EAX;
  1717. inc(pushedparasize,4);
  1718. end
  1719. else
  1720. begin
  1721. opsize:=S_W;
  1722. hreg:=R_AX;
  1723. inc(pushedparasize,2);
  1724. end;
  1725. if inlined then
  1726. begin
  1727. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1728. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,opsize,hreg,r)));
  1729. end
  1730. else
  1731. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,opsize,hreg)));
  1732. if not(R_EAX in unused) then
  1733. begin
  1734. emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
  1735. ungetregister32(R_EDI);
  1736. end;
  1737. end;
  1738. {$ifdef SUPPORT_MMX}
  1739. LOC_MMXREGISTER,
  1740. LOC_CMMXREGISTER:
  1741. begin
  1742. inc(pushedparasize,8); { was missing !!! (PM) }
  1743. emit_const_reg(
  1744. A_SUB,S_L,8,R_ESP);
  1745. {$ifdef GDB}
  1746. if (cs_debuginfo in aktmoduleswitches) and
  1747. (exprasmlist^.first=exprasmlist^.last) then
  1748. exprasmlist^.concat(new(pai_force_line,init));
  1749. {$endif GDB}
  1750. if inlined then
  1751. begin
  1752. r:=new_reference(procinfo^.framepointer,para_offset-pushedparasize);
  1753. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOVQ,S_NO,
  1754. p^.location.register,r)));
  1755. end
  1756. else
  1757. begin
  1758. r:=new_reference(R_ESP,0);
  1759. exprasmlist^.concat(new(paicpu,op_reg_ref(
  1760. A_MOVQ,S_NO,p^.location.register,r)));
  1761. end;
  1762. end;
  1763. {$endif SUPPORT_MMX}
  1764. end;
  1765. end;
  1766. {$endif CG11}
  1767. {*****************************************************************************
  1768. Emit Float Functions
  1769. *****************************************************************************}
  1770. procedure floatloadops(t : tfloattype;var op : tasmop;var s : topsize);
  1771. begin
  1772. case t of
  1773. s32real : begin
  1774. op:=A_FLD;
  1775. s:=S_FS;
  1776. end;
  1777. s64real : begin
  1778. op:=A_FLD;
  1779. { ???? }
  1780. s:=S_FL;
  1781. end;
  1782. s80real : begin
  1783. op:=A_FLD;
  1784. s:=S_FX;
  1785. end;
  1786. s64comp : begin
  1787. op:=A_FILD;
  1788. s:=S_IQ;
  1789. end;
  1790. else internalerror(17);
  1791. end;
  1792. end;
  1793. procedure floatload(t : tfloattype;const ref : treference);
  1794. var
  1795. op : tasmop;
  1796. s : topsize;
  1797. begin
  1798. floatloadops(t,op,s);
  1799. exprasmlist^.concat(new(paicpu,op_ref(op,s,
  1800. newreference(ref))));
  1801. inc(fpuvaroffset);
  1802. end;
  1803. procedure floatstoreops(t : tfloattype;var op : tasmop;var s : topsize);
  1804. begin
  1805. case t of
  1806. s32real : begin
  1807. op:=A_FSTP;
  1808. s:=S_FS;
  1809. end;
  1810. s64real : begin
  1811. op:=A_FSTP;
  1812. s:=S_FL;
  1813. end;
  1814. s80real : begin
  1815. op:=A_FSTP;
  1816. s:=S_FX;
  1817. end;
  1818. s64comp : begin
  1819. op:=A_FISTP;
  1820. s:=S_IQ;
  1821. end;
  1822. else
  1823. internalerror(17);
  1824. end;
  1825. end;
  1826. procedure floatstore(t : tfloattype;const ref : treference);
  1827. var
  1828. op : tasmop;
  1829. s : topsize;
  1830. begin
  1831. floatstoreops(t,op,s);
  1832. exprasmlist^.concat(new(paicpu,op_ref(op,s,
  1833. newreference(ref))));
  1834. dec(fpuvaroffset);
  1835. end;
  1836. {*****************************************************************************
  1837. Emit Functions
  1838. *****************************************************************************}
  1839. procedure concatcopy(source,dest : treference;size : longint;delsource,loadref : boolean);
  1840. const
  1841. isizes : array[0..3] of topsize=(S_L,S_B,S_W,S_B);
  1842. ishr : array[0..3] of byte=(2,0,1,0);
  1843. var
  1844. ecxpushed : boolean;
  1845. helpsize : longint;
  1846. i : byte;
  1847. reg8,reg32 : tregister;
  1848. swap : boolean;
  1849. procedure maybepushecx;
  1850. begin
  1851. if not(R_ECX in unused) then
  1852. begin
  1853. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_ECX)));
  1854. ecxpushed:=true;
  1855. end
  1856. else getexplicitregister32(R_ECX);
  1857. end;
  1858. begin
  1859. {$IfNDef regallocfix}
  1860. If delsource then
  1861. del_reference(source);
  1862. {$EndIf regallocfix}
  1863. if (not loadref) and
  1864. ((size<=8) or
  1865. (not(cs_littlesize in aktglobalswitches ) and (size<=12))) then
  1866. begin
  1867. helpsize:=size shr 2;
  1868. getexplicitregister32(R_EDI);
  1869. for i:=1 to helpsize do
  1870. begin
  1871. emit_ref_reg(A_MOV,S_L,newreference(source),R_EDI);
  1872. {$ifdef regallocfix}
  1873. If (size = 4) and delsource then
  1874. del_reference(source);
  1875. {$endif regallocfix}
  1876. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,newreference(dest))));
  1877. inc(source.offset,4);
  1878. inc(dest.offset,4);
  1879. dec(size,4);
  1880. end;
  1881. if size>1 then
  1882. begin
  1883. emit_ref_reg(A_MOV,S_W,newreference(source),R_DI);
  1884. {$ifdef regallocfix}
  1885. If (size = 2) and delsource then
  1886. del_reference(source);
  1887. {$endif regallocfix}
  1888. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_W,R_DI,newreference(dest))));
  1889. inc(source.offset,2);
  1890. inc(dest.offset,2);
  1891. dec(size,2);
  1892. end;
  1893. ungetregister32(R_EDI);
  1894. if size>0 then
  1895. begin
  1896. { and now look for an 8 bit register }
  1897. swap:=false;
  1898. if R_EAX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EAX))
  1899. else if R_EDX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EDX))
  1900. else if R_EBX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EBX))
  1901. else if R_ECX in unused then reg8:=reg32toreg8(getexplicitregister32(R_ECX))
  1902. else
  1903. begin
  1904. swap:=true;
  1905. { we need only to check 3 registers, because }
  1906. { one is always not index or base }
  1907. if (dest.base<>R_EAX) and (dest.index<>R_EAX) then
  1908. begin
  1909. reg8:=R_AL;
  1910. reg32:=R_EAX;
  1911. end
  1912. else if (dest.base<>R_EBX) and (dest.index<>R_EBX) then
  1913. begin
  1914. reg8:=R_BL;
  1915. reg32:=R_EBX;
  1916. end
  1917. else if (dest.base<>R_ECX) and (dest.index<>R_ECX) then
  1918. begin
  1919. reg8:=R_CL;
  1920. reg32:=R_ECX;
  1921. end;
  1922. end;
  1923. if swap then
  1924. { was earlier XCHG, of course nonsense }
  1925. begin
  1926. getexplicitregister32(R_EDI);
  1927. emit_reg_reg(A_MOV,S_L,reg32,R_EDI);
  1928. end;
  1929. emit_ref_reg(A_MOV,S_B,newreference(source),reg8);
  1930. {$ifdef regallocfix}
  1931. If delsource then
  1932. del_reference(source);
  1933. {$endif regallocfix}
  1934. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_B,reg8,newreference(dest))));
  1935. if swap then
  1936. begin
  1937. emit_reg_reg(A_MOV,S_L,R_EDI,reg32);
  1938. ungetregister32(R_EDI);
  1939. end
  1940. else
  1941. ungetregister(reg8);
  1942. end;
  1943. end
  1944. else
  1945. begin
  1946. getexplicitregister32(R_EDI);
  1947. emit_ref_reg(A_LEA,S_L,newreference(dest),R_EDI);
  1948. {$ifdef regallocfix}
  1949. {is this ok?? (JM)}
  1950. del_reference(dest);
  1951. {$endif regallocfix}
  1952. exprasmlist^.concat(new(pairegalloc,alloc(R_ESI)));
  1953. if loadref then
  1954. emit_ref_reg(A_MOV,S_L,newreference(source),R_ESI)
  1955. else
  1956. begin
  1957. emit_ref_reg(A_LEA,S_L,newreference(source),R_ESI);
  1958. {$ifdef regallocfix}
  1959. if delsource then
  1960. del_reference(source);
  1961. {$endif regallocfix}
  1962. end;
  1963. exprasmlist^.concat(new(paicpu,op_none(A_CLD,S_NO)));
  1964. ecxpushed:=false;
  1965. if cs_littlesize in aktglobalswitches then
  1966. begin
  1967. maybepushecx;
  1968. emit_const_reg(A_MOV,S_L,size,R_ECX);
  1969. exprasmlist^.concat(new(paicpu,op_none(A_REP,S_NO)));
  1970. exprasmlist^.concat(new(paicpu,op_none(A_MOVSB,S_NO)));
  1971. end
  1972. else
  1973. begin
  1974. helpsize:=size shr 2;
  1975. size:=size and 3;
  1976. if helpsize>1 then
  1977. begin
  1978. maybepushecx;
  1979. emit_const_reg(A_MOV,S_L,helpsize,R_ECX);
  1980. exprasmlist^.concat(new(paicpu,op_none(A_REP,S_NO)));
  1981. end;
  1982. if helpsize>0 then
  1983. exprasmlist^.concat(new(paicpu,op_none(A_MOVSD,S_NO)));
  1984. if size>1 then
  1985. begin
  1986. dec(size,2);
  1987. exprasmlist^.concat(new(paicpu,op_none(A_MOVSW,S_NO)));
  1988. end;
  1989. if size=1 then
  1990. exprasmlist^.concat(new(paicpu,op_none(A_MOVSB,S_NO)));
  1991. end;
  1992. ungetregister32(R_EDI);
  1993. exprasmlist^.concat(new(pairegalloc,dealloc(R_ESI)));
  1994. if ecxpushed then
  1995. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ECX)))
  1996. else
  1997. ungetregister32(R_ECX);
  1998. { loading SELF-reference again }
  1999. maybe_loadesi;
  2000. end;
  2001. if delsource then
  2002. ungetiftemp(source);
  2003. end;
  2004. procedure emitloadord2reg(const location:Tlocation;orddef:Porddef;
  2005. destreg:Tregister;delloc:boolean);
  2006. {A lot smaller and less bug sensitive than the original unfolded loads.}
  2007. var tai:Paicpu;
  2008. r:Preference;
  2009. begin
  2010. tai := nil;
  2011. case location.loc of
  2012. LOC_REGISTER,LOC_CREGISTER:
  2013. begin
  2014. case orddef^.typ of
  2015. u8bit:
  2016. tai:=new(paicpu,op_reg_reg(A_MOVZX,S_BL,location.register,destreg));
  2017. s8bit:
  2018. tai:=new(paicpu,op_reg_reg(A_MOVSX,S_BL,location.register,destreg));
  2019. u16bit:
  2020. tai:=new(paicpu,op_reg_reg(A_MOVZX,S_WL,location.register,destreg));
  2021. s16bit:
  2022. tai:=new(paicpu,op_reg_reg(A_MOVSX,S_WL,location.register,destreg));
  2023. u32bit,s32bit:
  2024. if location.register <> destreg then
  2025. tai:=new(paicpu,op_reg_reg(A_MOV,S_L,location.register,destreg));
  2026. end;
  2027. if delloc then
  2028. ungetregister(location.register);
  2029. end;
  2030. LOC_MEM,
  2031. LOC_REFERENCE:
  2032. begin
  2033. if location.reference.is_immediate then
  2034. tai:=new(paicpu,op_const_reg(A_MOV,S_L,location.reference.offset,destreg))
  2035. else
  2036. begin
  2037. r:=newreference(location.reference);
  2038. case orddef^.typ of
  2039. u8bit:
  2040. tai:=new(paicpu,op_ref_reg(A_MOVZX,S_BL,r,destreg));
  2041. s8bit:
  2042. tai:=new(paicpu,op_ref_reg(A_MOVSX,S_BL,r,destreg));
  2043. u16bit:
  2044. tai:=new(paicpu,op_ref_reg(A_MOVZX,S_WL,r,destreg));
  2045. s16bit:
  2046. tai:=new(paicpu,op_ref_reg(A_MOVSX,S_WL,r,destreg));
  2047. u32bit:
  2048. tai:=new(paicpu,op_ref_reg(A_MOV,S_L,r,destreg));
  2049. s32bit:
  2050. tai:=new(paicpu,op_ref_reg(A_MOV,S_L,r,destreg));
  2051. end;
  2052. end;
  2053. if delloc then
  2054. del_reference(location.reference);
  2055. end
  2056. else
  2057. internalerror(6);
  2058. end;
  2059. if assigned(tai) then
  2060. exprasmlist^.concat(tai);
  2061. end;
  2062. { if necessary ESI is reloaded after a call}
  2063. procedure maybe_loadesi;
  2064. var
  2065. hp : preference;
  2066. p : pprocinfo;
  2067. i : longint;
  2068. begin
  2069. if assigned(procinfo^._class) then
  2070. begin
  2071. exprasmlist^.concat(new(pairegalloc,alloc(R_ESI)));
  2072. if lexlevel>normal_function_level then
  2073. begin
  2074. new(hp);
  2075. reset_reference(hp^);
  2076. hp^.offset:=procinfo^.framepointer_offset;
  2077. hp^.base:=procinfo^.framepointer;
  2078. emit_ref_reg(A_MOV,S_L,hp,R_ESI);
  2079. p:=procinfo^.parent;
  2080. for i:=3 to lexlevel-1 do
  2081. begin
  2082. new(hp);
  2083. reset_reference(hp^);
  2084. hp^.offset:=p^.framepointer_offset;
  2085. hp^.base:=R_ESI;
  2086. emit_ref_reg(A_MOV,S_L,hp,R_ESI);
  2087. p:=p^.parent;
  2088. end;
  2089. new(hp);
  2090. reset_reference(hp^);
  2091. hp^.offset:=p^.selfpointer_offset;
  2092. hp^.base:=R_ESI;
  2093. emit_ref_reg(A_MOV,S_L,hp,R_ESI);
  2094. end
  2095. else
  2096. begin
  2097. new(hp);
  2098. reset_reference(hp^);
  2099. hp^.offset:=procinfo^.selfpointer_offset;
  2100. hp^.base:=procinfo^.framepointer;
  2101. emit_ref_reg(A_MOV,S_L,hp,R_ESI);
  2102. end;
  2103. end;
  2104. end;
  2105. {$ifndef CG11}
  2106. procedure maketojumpbool(p : ptree);
  2107. {
  2108. produces jumps to true respectively false labels using boolean expressions
  2109. }
  2110. var
  2111. opsize : topsize;
  2112. storepos : tfileposinfo;
  2113. begin
  2114. if p^.error then
  2115. exit;
  2116. storepos:=aktfilepos;
  2117. aktfilepos:=p^.fileinfo;
  2118. if is_boolean(p^.resulttype) then
  2119. begin
  2120. if is_constboolnode(p) then
  2121. begin
  2122. if p^.value<>0 then
  2123. emitjmp(C_None,truelabel)
  2124. else
  2125. emitjmp(C_None,falselabel);
  2126. end
  2127. else
  2128. begin
  2129. opsize:=def_opsize(p^.resulttype);
  2130. case p^.location.loc of
  2131. LOC_CREGISTER,LOC_REGISTER : begin
  2132. emit_reg_reg(A_OR,opsize,p^.location.register,
  2133. p^.location.register);
  2134. ungetregister(p^.location.register);
  2135. emitjmp(C_NZ,truelabel);
  2136. emitjmp(C_None,falselabel);
  2137. end;
  2138. LOC_MEM,LOC_REFERENCE : begin
  2139. emit_const_ref(
  2140. A_CMP,opsize,0,newreference(p^.location.reference));
  2141. del_reference(p^.location.reference);
  2142. emitjmp(C_NZ,truelabel);
  2143. emitjmp(C_None,falselabel);
  2144. end;
  2145. LOC_FLAGS : begin
  2146. emitjmp(flag_2_cond[p^.location.resflags],truelabel);
  2147. emitjmp(C_None,falselabel);
  2148. end;
  2149. end;
  2150. end;
  2151. end
  2152. else
  2153. CGMessage(type_e_mismatch);
  2154. aktfilepos:=storepos;
  2155. end;
  2156. { produces if necessary overflowcode }
  2157. procedure emitoverflowcheck(p:ptree);
  2158. var
  2159. hl : pasmlabel;
  2160. begin
  2161. if not(cs_check_overflow in aktlocalswitches) then
  2162. exit;
  2163. getlabel(hl);
  2164. if not ((p^.resulttype^.deftype=pointerdef) or
  2165. ((p^.resulttype^.deftype=orddef) and
  2166. (porddef(p^.resulttype)^.typ in [u64bit,u16bit,u32bit,u8bit,uchar,
  2167. bool8bit,bool16bit,bool32bit]))) then
  2168. emitjmp(C_NO,hl)
  2169. else
  2170. emitjmp(C_NB,hl);
  2171. emitcall('FPC_OVERFLOW');
  2172. emitlab(hl);
  2173. end;
  2174. { produces range check code, while one of the operands is a 64 bit
  2175. integer }
  2176. procedure emitrangecheck64(p : ptree;todef : pdef);
  2177. begin
  2178. CGMessage(cg_w_64bit_range_check_not_supported);
  2179. {internalerror(28699);}
  2180. end;
  2181. { produces if necessary rangecheckcode }
  2182. procedure emitrangecheck(p:ptree;todef:pdef);
  2183. {
  2184. generate range checking code for the value at location t. The
  2185. type used is the checked against todefs ranges. fromdef (p.resulttype)
  2186. is the original type used at that location, when both defs are
  2187. equal the check is also insert (needed for succ,pref,inc,dec)
  2188. }
  2189. var
  2190. neglabel,
  2191. poslabel : pasmlabel;
  2192. href : treference;
  2193. rstr : string;
  2194. hreg : tregister;
  2195. opsize : topsize;
  2196. op : tasmop;
  2197. fromdef : pdef;
  2198. lto,hto,
  2199. lfrom,hfrom : longint;
  2200. doublebound,
  2201. is_reg,
  2202. popecx : boolean;
  2203. begin
  2204. { range checking on and range checkable value? }
  2205. if not(cs_check_range in aktlocalswitches) or
  2206. not(todef^.deftype in [orddef,enumdef,arraydef]) then
  2207. exit;
  2208. { only check when assigning to scalar, subranges are different,
  2209. when todef=fromdef then the check is always generated }
  2210. fromdef:=p^.resulttype;
  2211. if is_64bitint(fromdef) or is_64bitint(todef) then
  2212. begin
  2213. emitrangecheck64(p,todef);
  2214. exit;
  2215. end;
  2216. {we also need lto and hto when checking if we need to use doublebound!
  2217. (JM)}
  2218. getrange(todef,lto,hto);
  2219. if todef<>fromdef then
  2220. begin
  2221. getrange(p^.resulttype,lfrom,hfrom);
  2222. { first check for not being u32bit, then if the to is bigger than
  2223. from }
  2224. if (lto<hto) and (lfrom<hfrom) and
  2225. (lto<=lfrom) and (hto>=hfrom) then
  2226. exit;
  2227. end;
  2228. { generate the rangecheck code for the def where we are going to
  2229. store the result }
  2230. doublebound:=false;
  2231. case todef^.deftype of
  2232. orddef :
  2233. begin
  2234. porddef(todef)^.genrangecheck;
  2235. rstr:=porddef(todef)^.getrangecheckstring;
  2236. doublebound:=(porddef(todef)^.typ=u32bit) and (lto>hto);
  2237. end;
  2238. enumdef :
  2239. begin
  2240. penumdef(todef)^.genrangecheck;
  2241. rstr:=penumdef(todef)^.getrangecheckstring;
  2242. end;
  2243. arraydef :
  2244. begin
  2245. parraydef(todef)^.genrangecheck;
  2246. rstr:=parraydef(todef)^.getrangecheckstring;
  2247. doublebound:=(lto>hto);
  2248. end;
  2249. end;
  2250. { get op and opsize }
  2251. opsize:=def2def_opsize(fromdef,u32bitdef);
  2252. if opsize in [S_B,S_W,S_L] then
  2253. op:=A_MOV
  2254. else
  2255. if is_signed(fromdef) then
  2256. op:=A_MOVSX
  2257. else
  2258. op:=A_MOVZX;
  2259. is_reg:=(p^.location.loc in [LOC_REGISTER,LOC_CREGISTER]);
  2260. if is_reg then
  2261. hreg:=p^.location.register;
  2262. if not target_os.use_bound_instruction then
  2263. begin
  2264. { FPC_BOUNDCHECK needs to be called with
  2265. %ecx - value
  2266. %edi - pointer to the ranges }
  2267. popecx:=false;
  2268. if not(is_reg) or
  2269. (p^.location.register<>R_ECX) then
  2270. begin
  2271. if not(R_ECX in unused) then
  2272. begin
  2273. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_ECX)));
  2274. popecx:=true;
  2275. end
  2276. else exprasmlist^.concat(new(pairegalloc,alloc(R_ECX)));
  2277. if is_reg then
  2278. emit_reg_reg(op,opsize,p^.location.register,R_ECX)
  2279. else
  2280. emit_ref_reg(op,opsize,newreference(p^.location.reference),R_ECX);
  2281. end;
  2282. if doublebound then
  2283. begin
  2284. getlabel(neglabel);
  2285. getlabel(poslabel);
  2286. emit_reg_reg(A_OR,S_L,R_ECX,R_ECX);
  2287. emitjmp(C_L,neglabel);
  2288. end;
  2289. { insert bound instruction only }
  2290. getexplicitregister32(R_EDI);
  2291. exprasmlist^.concat(new(paicpu,op_sym_ofs_reg(A_MOV,S_L,newasmsymbol(rstr),0,R_EDI)));
  2292. emitcall('FPC_BOUNDCHECK');
  2293. ungetregister32(R_EDI);
  2294. { u32bit needs 2 checks }
  2295. if doublebound then
  2296. begin
  2297. emitjmp(C_None,poslabel);
  2298. emitlab(neglabel);
  2299. getexplicitregister32(R_EDI);
  2300. exprasmlist^.concat(new(paicpu,op_sym_ofs_reg(A_MOV,S_L,newasmsymbol(rstr),8,R_EDI)));
  2301. emitcall('FPC_BOUNDCHECK');
  2302. ungetregister32(R_EDI);
  2303. emitlab(poslabel);
  2304. end;
  2305. if popecx then
  2306. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ECX)))
  2307. else exprasmlist^.concat(new(pairegalloc,dealloc(R_ECX)));
  2308. end
  2309. else
  2310. begin
  2311. reset_reference(href);
  2312. href.symbol:=newasmsymbol(rstr);
  2313. { load the value in a register }
  2314. if is_reg then
  2315. begin
  2316. { be sure that hreg is a 32 bit reg, if not load it in %edi }
  2317. if p^.location.register in [R_EAX..R_EDI] then
  2318. hreg:=p^.location.register
  2319. else
  2320. begin
  2321. getexplicitregister32(R_EDI);
  2322. emit_reg_reg(op,opsize,p^.location.register,R_EDI);
  2323. hreg:=R_EDI;
  2324. end;
  2325. end
  2326. else
  2327. begin
  2328. getexplicitregister32(R_EDI);
  2329. emit_ref_reg(op,opsize,newreference(p^.location.reference),R_EDI);
  2330. hreg:=R_EDI;
  2331. end;
  2332. if doublebound then
  2333. begin
  2334. getlabel(neglabel);
  2335. getlabel(poslabel);
  2336. emit_reg_reg(A_TEST,S_L,hreg,hreg);
  2337. emitjmp(C_L,neglabel);
  2338. end;
  2339. { insert bound instruction only }
  2340. exprasmlist^.concat(new(paicpu,op_reg_ref(A_BOUND,S_L,hreg,newreference(href))));
  2341. { u32bit needs 2 checks }
  2342. if doublebound then
  2343. begin
  2344. href.offset:=8;
  2345. emitjmp(C_None,poslabel);
  2346. emitlab(neglabel);
  2347. exprasmlist^.concat(new(paicpu,op_reg_ref(A_BOUND,S_L,hreg,newreference(href))));
  2348. emitlab(poslabel);
  2349. end;
  2350. if hreg = R_EDI then
  2351. ungetregister32(R_EDI);
  2352. end;
  2353. end;
  2354. { DO NOT RELY on the fact that the ptree is not yet swaped
  2355. because of inlining code PM }
  2356. procedure firstcomplex(p : ptree);
  2357. var
  2358. hp : ptree;
  2359. begin
  2360. { always calculate boolean AND and OR from left to right }
  2361. if (p^.treetype in [orn,andn]) and
  2362. (p^.left^.resulttype^.deftype=orddef) and
  2363. (porddef(p^.left^.resulttype)^.typ in [bool8bit,bool16bit,bool32bit]) then
  2364. begin
  2365. { p^.swaped:=false}
  2366. if p^.swaped then
  2367. internalerror(234234);
  2368. end
  2369. else
  2370. if (p^.left^.registers32<p^.right^.registers32) and
  2371. { the following check is appropriate, because all }
  2372. { 4 registers are rarely used and it is thereby }
  2373. { achieved that the extra code is being dropped }
  2374. { by exchanging not commutative operators }
  2375. (p^.right^.registers32<=4) then
  2376. begin
  2377. hp:=p^.left;
  2378. p^.left:=p^.right;
  2379. p^.right:=hp;
  2380. p^.swaped:=not p^.swaped;
  2381. end;
  2382. {else
  2383. p^.swaped:=false; do not modify }
  2384. end;
  2385. {$endif}
  2386. {*****************************************************************************
  2387. Entry/Exit Code Functions
  2388. *****************************************************************************}
  2389. procedure genprofilecode;
  2390. var
  2391. pl : pasmlabel;
  2392. begin
  2393. if (po_assembler in aktprocsym^.definition^.procoptions) then
  2394. exit;
  2395. case target_info.target of
  2396. target_i386_freebsd,
  2397. target_i386_linux:
  2398. begin
  2399. getaddrlabel(pl);
  2400. emitcall('mcount');
  2401. exprasmlist^.insert(new(paicpu,op_sym_ofs_reg(A_MOV,S_L,pl,0,R_EDX)));
  2402. exprasmlist^.insert(new(pai_section,init(sec_code)));
  2403. exprasmlist^.insert(new(pai_const,init_32bit(0)));
  2404. exprasmlist^.insert(new(pai_label,init(pl)));
  2405. exprasmlist^.insert(new(pai_align,init(4)));
  2406. exprasmlist^.insert(new(pai_section,init(sec_data)));
  2407. end;
  2408. target_i386_go32v2:
  2409. begin
  2410. emitinsertcall('MCOUNT');
  2411. end;
  2412. end;
  2413. end;
  2414. procedure generate_interrupt_stackframe_entry;
  2415. begin
  2416. { save the registers of an interrupt procedure }
  2417. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EAX)));
  2418. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EBX)));
  2419. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_ECX)));
  2420. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EDX)));
  2421. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_ESI)));
  2422. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  2423. { .... also the segment registers }
  2424. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_W,R_DS)));
  2425. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_W,R_ES)));
  2426. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_W,R_FS)));
  2427. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_W,R_GS)));
  2428. end;
  2429. procedure generate_interrupt_stackframe_exit;
  2430. begin
  2431. { restore the registers of an interrupt procedure }
  2432. { this was all with entrycode instead of exitcode !!}
  2433. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_EAX)));
  2434. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_EBX)));
  2435. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_ECX)));
  2436. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_EDX)));
  2437. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_ESI)));
  2438. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_EDI)));
  2439. { .... also the segment registers }
  2440. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_W,R_DS)));
  2441. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_W,R_ES)));
  2442. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_W,R_FS)));
  2443. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_W,R_GS)));
  2444. { this restores the flags }
  2445. procinfo^.aktexitcode^.concat(new(paicpu,op_none(A_IRET,S_NO)));
  2446. end;
  2447. { generates the code for threadvar initialisation }
  2448. procedure initialize_threadvar(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  2449. var
  2450. hr : treference;
  2451. begin
  2452. if (psym(p)^.typ=varsym) and
  2453. (vo_is_thread_var in pvarsym(p)^.varoptions) then
  2454. begin
  2455. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,pvarsym(p)^.getsize)));
  2456. reset_reference(hr);
  2457. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  2458. emitpushreferenceaddr(hr);
  2459. emitcall('FPC_INIT_THREADVAR');
  2460. end;
  2461. end;
  2462. { initilizes data of type t }
  2463. { if is_already_ref is true then the routines assumes }
  2464. { that r points to the data to initialize }
  2465. procedure initialize(t : pdef;const ref : treference;is_already_ref : boolean);
  2466. var
  2467. hr : treference;
  2468. begin
  2469. if is_ansistring(t) or
  2470. is_widestring(t) then
  2471. begin
  2472. emit_const_ref(A_MOV,S_L,0,
  2473. newreference(ref));
  2474. end
  2475. else
  2476. begin
  2477. reset_reference(hr);
  2478. hr.symbol:=t^.get_inittable_label;
  2479. emitpushreferenceaddr(hr);
  2480. if is_already_ref then
  2481. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,
  2482. newreference(ref))))
  2483. else
  2484. emitpushreferenceaddr(ref);
  2485. emitcall('FPC_INITIALIZE');
  2486. end;
  2487. end;
  2488. { finalizes data of type t }
  2489. { if is_already_ref is true then the routines assumes }
  2490. { that r points to the data to finalizes }
  2491. procedure finalize(t : pdef;const ref : treference;is_already_ref : boolean);
  2492. var
  2493. r : treference;
  2494. begin
  2495. if is_ansistring(t) or
  2496. is_widestring(t) then
  2497. begin
  2498. decrstringref(t,ref);
  2499. end
  2500. else
  2501. begin
  2502. reset_reference(r);
  2503. r.symbol:=t^.get_inittable_label;
  2504. emitpushreferenceaddr(r);
  2505. if is_already_ref then
  2506. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,
  2507. newreference(ref))))
  2508. else
  2509. emitpushreferenceaddr(ref);
  2510. emitcall('FPC_FINALIZE');
  2511. end;
  2512. end;
  2513. { generates the code for initialisation of local data }
  2514. procedure initialize_data(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  2515. var
  2516. hr : treference;
  2517. begin
  2518. if (psym(p)^.typ=varsym) and
  2519. assigned(pvarsym(p)^.vartype.def) and
  2520. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  2521. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  2522. pvarsym(p)^.vartype.def^.needs_inittable then
  2523. begin
  2524. if assigned(procinfo) then
  2525. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  2526. reset_reference(hr);
  2527. if psym(p)^.owner^.symtabletype in [localsymtable,inlinelocalsymtable] then
  2528. begin
  2529. hr.base:=procinfo^.framepointer;
  2530. hr.offset:=-pvarsym(p)^.address+pvarsym(p)^.owner^.address_fixup;
  2531. end
  2532. else
  2533. begin
  2534. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  2535. end;
  2536. initialize(pvarsym(p)^.vartype.def,hr,false);
  2537. end;
  2538. end;
  2539. { generates the code for incrementing the reference count of parameters }
  2540. procedure incr_data(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  2541. var
  2542. hr : treference;
  2543. begin
  2544. if (psym(p)^.typ=varsym) and
  2545. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  2546. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  2547. pvarsym(p)^.vartype.def^.needs_inittable and
  2548. (not assigned(pvarsym(p)^.localvarsym)) and
  2549. ((pvarsym(p)^.varspez=vs_value) {or
  2550. (pvarsym(p)^.varspez=vs_const) and
  2551. not(dont_copy_const_param(pvarsym(p)^.definition))}) then
  2552. begin
  2553. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  2554. reset_reference(hr);
  2555. hr.symbol:=pvarsym(p)^.vartype.def^.get_inittable_label;
  2556. emitpushreferenceaddr(hr);
  2557. reset_reference(hr);
  2558. hr.base:=procinfo^.framepointer;
  2559. hr.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  2560. emitpushreferenceaddr(hr);
  2561. reset_reference(hr);
  2562. emitcall('FPC_ADDREF');
  2563. end;
  2564. end;
  2565. { generates the code for finalisation of local data }
  2566. procedure finalize_data(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  2567. var
  2568. hr : treference;
  2569. begin
  2570. if (psym(p)^.typ=varsym) and
  2571. assigned(pvarsym(p)^.vartype.def) and
  2572. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  2573. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  2574. (not assigned(pvarsym(p)^.localvarsym)) and
  2575. pvarsym(p)^.vartype.def^.needs_inittable then
  2576. begin
  2577. { not all kind of parameters need to be finalized }
  2578. if (psym(p)^.owner^.symtabletype=parasymtable) and
  2579. (pvarsym(p)^.varspez in [vs_out,vs_var,vs_const]) then
  2580. exit;
  2581. if assigned(procinfo) then
  2582. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  2583. reset_reference(hr);
  2584. case psym(p)^.owner^.symtabletype of
  2585. localsymtable,inlinelocalsymtable:
  2586. begin
  2587. hr.base:=procinfo^.framepointer;
  2588. hr.offset:=-pvarsym(p)^.address+pvarsym(p)^.owner^.address_fixup;
  2589. end;
  2590. parasymtable,inlineparasymtable:
  2591. begin
  2592. hr.base:=procinfo^.framepointer;
  2593. hr.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  2594. end;
  2595. else
  2596. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  2597. end;
  2598. finalize(pvarsym(p)^.vartype.def,hr,false);
  2599. end;
  2600. end;
  2601. { generates the code to make local copies of the value parameters }
  2602. procedure copyvalueparas(p : pnamedindexobject);{$ifndef fpc}far;{$endif}
  2603. var
  2604. href1,href2 : treference;
  2605. r : preference;
  2606. power,len : longint;
  2607. opsize : topsize;
  2608. again,ok : pasmlabel;
  2609. begin
  2610. if (psym(p)^.typ=varsym) and
  2611. (pvarsym(p)^.varspez=vs_value) and
  2612. (push_addr_param(pvarsym(p)^.vartype.def)) then
  2613. begin
  2614. if is_open_array(pvarsym(p)^.vartype.def) or
  2615. is_array_of_const(pvarsym(p)^.vartype.def) then
  2616. begin
  2617. { get stack space }
  2618. new(r);
  2619. reset_reference(r^);
  2620. r^.base:=procinfo^.framepointer;
  2621. r^.offset:=pvarsym(p)^.address+4+procinfo^.para_offset;
  2622. getexplicitregister32(R_EDI);
  2623. exprasmlist^.concat(new(paicpu,
  2624. op_ref_reg(A_MOV,S_L,r,R_EDI)));
  2625. exprasmlist^.concat(new(paicpu,
  2626. op_reg(A_INC,S_L,R_EDI)));
  2627. if (parraydef(pvarsym(p)^.vartype.def)^.elesize<>1) then
  2628. begin
  2629. if ispowerof2(parraydef(pvarsym(p)^.vartype.def)^.elesize, power) then
  2630. exprasmlist^.concat(new(paicpu,
  2631. op_const_reg(A_SHL,S_L,
  2632. power,R_EDI)))
  2633. else
  2634. exprasmlist^.concat(new(paicpu,
  2635. op_const_reg(A_IMUL,S_L,
  2636. parraydef(pvarsym(p)^.vartype.def)^.elesize,R_EDI)));
  2637. end;
  2638. {$ifndef NOTARGETWIN32}
  2639. { windows guards only a few pages for stack growing, }
  2640. { so we have to access every page first }
  2641. if target_os.id=os_i386_win32 then
  2642. begin
  2643. getlabel(again);
  2644. getlabel(ok);
  2645. emitlab(again);
  2646. exprasmlist^.concat(new(paicpu,
  2647. op_const_reg(A_CMP,S_L,winstackpagesize,R_EDI)));
  2648. emitjmp(C_C,ok);
  2649. exprasmlist^.concat(new(paicpu,
  2650. op_const_reg(A_SUB,S_L,winstackpagesize-4,R_ESP)));
  2651. exprasmlist^.concat(new(paicpu,
  2652. op_reg(A_PUSH,S_L,R_EAX)));
  2653. exprasmlist^.concat(new(paicpu,
  2654. op_const_reg(A_SUB,S_L,winstackpagesize,R_EDI)));
  2655. emitjmp(C_None,again);
  2656. emitlab(ok);
  2657. exprasmlist^.concat(new(paicpu,
  2658. op_reg_reg(A_SUB,S_L,R_EDI,R_ESP)));
  2659. ungetregister32(R_EDI);
  2660. { now reload EDI }
  2661. new(r);
  2662. reset_reference(r^);
  2663. r^.base:=procinfo^.framepointer;
  2664. r^.offset:=pvarsym(p)^.address+4+procinfo^.para_offset;
  2665. getexplicitregister32(R_EDI);
  2666. exprasmlist^.concat(new(paicpu,
  2667. op_ref_reg(A_MOV,S_L,r,R_EDI)));
  2668. exprasmlist^.concat(new(paicpu,
  2669. op_reg(A_INC,S_L,R_EDI)));
  2670. if (parraydef(pvarsym(p)^.vartype.def)^.elesize<>1) then
  2671. begin
  2672. if ispowerof2(parraydef(pvarsym(p)^.vartype.def)^.elesize, power) then
  2673. exprasmlist^.concat(new(paicpu,
  2674. op_const_reg(A_SHL,S_L,
  2675. power,R_EDI)))
  2676. else
  2677. exprasmlist^.concat(new(paicpu,
  2678. op_const_reg(A_IMUL,S_L,
  2679. parraydef(pvarsym(p)^.vartype.def)^.elesize,R_EDI)));
  2680. end;
  2681. end
  2682. else
  2683. {$endif NOTARGETWIN32}
  2684. exprasmlist^.concat(new(paicpu,
  2685. op_reg_reg(A_SUB,S_L,R_EDI,R_ESP)));
  2686. { load destination }
  2687. exprasmlist^.concat(new(paicpu,
  2688. op_reg_reg(A_MOV,S_L,R_ESP,R_EDI)));
  2689. { don't destroy the registers! }
  2690. exprasmlist^.concat(new(paicpu,
  2691. op_reg(A_PUSH,S_L,R_ECX)));
  2692. exprasmlist^.concat(new(paicpu,
  2693. op_reg(A_PUSH,S_L,R_ESI)));
  2694. { load count }
  2695. new(r);
  2696. reset_reference(r^);
  2697. r^.base:=procinfo^.framepointer;
  2698. r^.offset:=pvarsym(p)^.address+4+procinfo^.para_offset;
  2699. exprasmlist^.concat(new(paicpu,
  2700. op_ref_reg(A_MOV,S_L,r,R_ECX)));
  2701. { load source }
  2702. new(r);
  2703. reset_reference(r^);
  2704. r^.base:=procinfo^.framepointer;
  2705. r^.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  2706. exprasmlist^.concat(new(paicpu,
  2707. op_ref_reg(A_MOV,S_L,r,R_ESI)));
  2708. { scheduled .... }
  2709. exprasmlist^.concat(new(paicpu,
  2710. op_reg(A_INC,S_L,R_ECX)));
  2711. { calculate size }
  2712. len:=parraydef(pvarsym(p)^.vartype.def)^.elesize;
  2713. opsize:=S_B;
  2714. if (len and 3)=0 then
  2715. begin
  2716. opsize:=S_L;
  2717. len:=len shr 2;
  2718. end
  2719. else
  2720. if (len and 1)=0 then
  2721. begin
  2722. opsize:=S_W;
  2723. len:=len shr 1;
  2724. end;
  2725. if ispowerof2(len, power) then
  2726. exprasmlist^.concat(new(paicpu,
  2727. op_const_reg(A_SHL,S_L,
  2728. power,R_ECX)))
  2729. else
  2730. exprasmlist^.concat(new(paicpu,
  2731. op_const_reg(A_IMUL,S_L,len,R_ECX)));
  2732. exprasmlist^.concat(new(paicpu,
  2733. op_none(A_REP,S_NO)));
  2734. case opsize of
  2735. S_B : exprasmlist^.concat(new(paicpu,op_none(A_MOVSB,S_NO)));
  2736. S_W : exprasmlist^.concat(new(paicpu,op_none(A_MOVSW,S_NO)));
  2737. S_L : exprasmlist^.concat(new(paicpu,op_none(A_MOVSD,S_NO)));
  2738. end;
  2739. ungetregister32(R_EDI);
  2740. exprasmlist^.concat(new(paicpu,
  2741. op_reg(A_POP,S_L,R_ESI)));
  2742. exprasmlist^.concat(new(paicpu,
  2743. op_reg(A_POP,S_L,R_ECX)));
  2744. { patch the new address }
  2745. new(r);
  2746. reset_reference(r^);
  2747. r^.base:=procinfo^.framepointer;
  2748. r^.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  2749. exprasmlist^.concat(new(paicpu,
  2750. op_reg_ref(A_MOV,S_L,R_ESP,r)));
  2751. end
  2752. else
  2753. if is_shortstring(pvarsym(p)^.vartype.def) then
  2754. begin
  2755. reset_reference(href1);
  2756. href1.base:=procinfo^.framepointer;
  2757. href1.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  2758. reset_reference(href2);
  2759. href2.base:=procinfo^.framepointer;
  2760. href2.offset:=-pvarsym(p)^.localvarsym^.address+pvarsym(p)^.localvarsym^.owner^.address_fixup;
  2761. copyshortstring(href2,href1,pstringdef(pvarsym(p)^.vartype.def)^.len,true,false);
  2762. end
  2763. else
  2764. begin
  2765. reset_reference(href1);
  2766. href1.base:=procinfo^.framepointer;
  2767. href1.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  2768. reset_reference(href2);
  2769. href2.base:=procinfo^.framepointer;
  2770. href2.offset:=-pvarsym(p)^.localvarsym^.address+pvarsym(p)^.localvarsym^.owner^.address_fixup;
  2771. concatcopy(href1,href2,pvarsym(p)^.vartype.def^.size,true,true);
  2772. end;
  2773. end;
  2774. end;
  2775. procedure inittempansistrings;
  2776. var
  2777. hp : ptemprecord;
  2778. r : preference;
  2779. begin
  2780. hp:=templist;
  2781. while assigned(hp) do
  2782. begin
  2783. if hp^.temptype in [tt_ansistring,tt_freeansistring] then
  2784. begin
  2785. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  2786. new(r);
  2787. reset_reference(r^);
  2788. r^.base:=procinfo^.framepointer;
  2789. r^.offset:=hp^.pos;
  2790. emit_const_ref(A_MOV,S_L,0,r);
  2791. end;
  2792. hp:=hp^.next;
  2793. end;
  2794. end;
  2795. procedure finalizetempansistrings;
  2796. var
  2797. hp : ptemprecord;
  2798. hr : treference;
  2799. begin
  2800. hp:=templist;
  2801. while assigned(hp) do
  2802. begin
  2803. if hp^.temptype in [tt_ansistring,tt_freeansistring] then
  2804. begin
  2805. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  2806. reset_reference(hr);
  2807. hr.base:=procinfo^.framepointer;
  2808. hr.offset:=hp^.pos;
  2809. emitpushreferenceaddr(hr);
  2810. emitcall('FPC_ANSISTR_DECR_REF');
  2811. end;
  2812. hp:=hp^.next;
  2813. end;
  2814. end;
  2815. var
  2816. ls : longint;
  2817. procedure largest_size(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  2818. begin
  2819. if (psym(p)^.typ=varsym) and
  2820. (pvarsym(p)^.getvaluesize>ls) then
  2821. ls:=pvarsym(p)^.getvaluesize;
  2822. end;
  2823. procedure alignstack(alist : paasmoutput);
  2824. begin
  2825. {$ifdef dummy}
  2826. if (cs_optimize in aktglobalswitches) and
  2827. (aktoptprocessor in [classp5,classp6]) then
  2828. begin
  2829. ls:=0;
  2830. aktprocsym^.definition^.localst^.foreach({$ifndef TP}@{$endif}largest_size);
  2831. if ls>=8 then
  2832. alist^.insert(new(paicpu,op_const_reg(A_AND,S_L,-8,R_ESP)));
  2833. end;
  2834. {$endif dummy}
  2835. end;
  2836. procedure genentrycode(alist : paasmoutput;const proc_names:Tstringcontainer;make_global:boolean;
  2837. stackframe:longint;
  2838. var parasize:longint;var nostackframe:boolean;
  2839. inlined : boolean);
  2840. {
  2841. Generates the entry code for a procedure
  2842. }
  2843. var
  2844. hs : string;
  2845. {$ifdef GDB}
  2846. stab_function_name : Pai_stab_function_name;
  2847. {$endif GDB}
  2848. hr : preference;
  2849. p : psymtable;
  2850. r : treference;
  2851. oldlist,
  2852. oldexprasmlist : paasmoutput;
  2853. again : pasmlabel;
  2854. i : longint;
  2855. begin
  2856. oldexprasmlist:=exprasmlist;
  2857. exprasmlist:=alist;
  2858. if (not inlined) and (aktprocsym^.definition^.proctypeoption=potype_proginit) then
  2859. begin
  2860. emitinsertcall('FPC_INITIALIZEUNITS');
  2861. if target_info.target=target_I386_WIN32 then
  2862. begin
  2863. new(hr);
  2864. reset_reference(hr^);
  2865. hr^.symbol:=newasmsymbol(
  2866. 'U_SYSWIN32_ISCONSOLE');
  2867. if apptype=at_cui then
  2868. exprasmlist^.insert(new(paicpu,op_const_ref(A_MOV,S_B,
  2869. 1,hr)))
  2870. else
  2871. exprasmlist^.insert(new(paicpu,op_const_ref(A_MOV,S_B,
  2872. 0,hr)));
  2873. end;
  2874. oldlist:=exprasmlist;
  2875. exprasmlist:=new(paasmoutput,init);
  2876. p:=symtablestack;
  2877. while assigned(p) do
  2878. begin
  2879. p^.foreach({$ifndef TP}@{$endif}initialize_threadvar);
  2880. p:=p^.next;
  2881. end;
  2882. oldlist^.insertlist(exprasmlist);
  2883. dispose(exprasmlist,done);
  2884. exprasmlist:=oldlist;
  2885. end;
  2886. {$ifdef GDB}
  2887. if (not inlined) and (cs_debuginfo in aktmoduleswitches) then
  2888. exprasmlist^.insert(new(pai_force_line,init));
  2889. {$endif GDB}
  2890. { a constructor needs a help procedure }
  2891. if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
  2892. begin
  2893. if procinfo^._class^.is_class then
  2894. begin
  2895. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  2896. exprasmlist^.insert(new(paicpu,op_cond_sym(A_Jcc,C_Z,S_NO,faillabel)));
  2897. emitinsertcall('FPC_NEW_CLASS');
  2898. end
  2899. else
  2900. begin
  2901. exprasmlist^.insert(new(paicpu,op_cond_sym(A_Jcc,C_Z,S_NO,faillabel)));
  2902. emitinsertcall('FPC_HELP_CONSTRUCTOR');
  2903. getexplicitregister32(R_EDI);
  2904. exprasmlist^.insert(new(paicpu,op_const_reg(A_MOV,S_L,procinfo^._class^.vmt_offset,R_EDI)));
  2905. end;
  2906. end;
  2907. { don't load ESI, does the caller }
  2908. { we must do it for local function }
  2909. { that can be called from a foreach }
  2910. { of another object than self !! PM }
  2911. if assigned(procinfo^._class) and
  2912. (lexlevel>normal_function_level) then
  2913. maybe_loadesi;
  2914. { When message method contains self as a parameter,
  2915. we must load it into ESI }
  2916. If (po_containsself in aktprocsym^.definition^.procoptions) then
  2917. begin
  2918. new(hr);
  2919. reset_reference(hr^);
  2920. hr^.offset:=procinfo^.selfpointer_offset;
  2921. hr^.base:=procinfo^.framepointer;
  2922. exprasmlist^.insert(new(paicpu,op_ref_reg(A_MOV,S_L,hr,R_ESI)));
  2923. exprasmlist^.insert(new(pairegalloc,alloc(R_ESI)));
  2924. end;
  2925. { should we save edi,esi,ebx like C ? }
  2926. if (po_savestdregs in aktprocsym^.definition^.procoptions) then
  2927. begin
  2928. if (aktprocsym^.definition^.usedregisters and ($80 shr byte(R_EBX)))<>0 then
  2929. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EBX)));
  2930. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_ESI)));
  2931. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  2932. end;
  2933. { for the save all registers we can simply use a pusha,popa which
  2934. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  2935. if (po_saveregisters in aktprocsym^.definition^.procoptions) then
  2936. begin
  2937. exprasmlist^.insert(new(paicpu,op_none(A_PUSHA,S_L)));
  2938. end;
  2939. { omit stack frame ? }
  2940. if not inlined then
  2941. if procinfo^.framepointer=stack_pointer then
  2942. begin
  2943. CGMessage(cg_d_stackframe_omited);
  2944. nostackframe:=true;
  2945. if (aktprocsym^.definition^.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  2946. parasize:=0
  2947. else
  2948. parasize:=aktprocsym^.definition^.parast^.datasize+procinfo^.para_offset-4;
  2949. if stackframe<>0 then
  2950. exprasmlist^.insert(new(paicpu,
  2951. op_const_reg(A_SUB,S_L,stackframe,R_ESP)));
  2952. end
  2953. else
  2954. begin
  2955. alignstack(alist);
  2956. if (aktprocsym^.definition^.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  2957. parasize:=0
  2958. else
  2959. parasize:=aktprocsym^.definition^.parast^.datasize+procinfo^.para_offset-8;
  2960. nostackframe:=false;
  2961. if stackframe<>0 then
  2962. begin
  2963. {$ifdef unused}
  2964. if (cs_littlesize in aktglobalswitches) and (stackframe<=65535) then
  2965. begin
  2966. if (cs_check_stack in aktlocalswitches) and
  2967. not(target_info.target in [target_386_freebsd,
  2968. target_i386_linux,target_i386_win32]) then
  2969. begin
  2970. emitinsertcall('FPC_STACKCHECK');
  2971. exprasmlist^.insert(new(paicpu,op_const(A_PUSH,S_L,stackframe)));
  2972. end;
  2973. if cs_profile in aktmoduleswitches then
  2974. genprofilecode;
  2975. { %edi is already saved when pocdecl is used
  2976. if ((target_info.target=target_linux) or (target_info.target=target_freebsd)) and
  2977. ((aktprocsym^.definition^.options and poexports)<>0) then
  2978. exprasmlist^.insert(new(Paicpu,op_reg(A_PUSH,S_L,R_EDI))); }
  2979. { ATTENTION:
  2980. never use ENTER in linux !!! (or freebsd MvdV)
  2981. the stack page fault does not support it PM }
  2982. exprasmlist^.insert(new(paicpu,op_const_const(A_ENTER,S_NO,stackframe,0)))
  2983. end
  2984. else
  2985. {$endif unused}
  2986. begin
  2987. { windows guards only a few pages for stack growing, }
  2988. { so we have to access every page first }
  2989. if (target_os.id=os_i386_win32) and
  2990. (stackframe>=winstackpagesize) then
  2991. begin
  2992. if stackframe div winstackpagesize<=5 then
  2993. begin
  2994. exprasmlist^.insert(new(paicpu,op_const_reg(A_SUB,S_L,stackframe-4,R_ESP)));
  2995. for i:=1 to stackframe div winstackpagesize do
  2996. begin
  2997. hr:=new_reference(R_ESP,stackframe-i*winstackpagesize);
  2998. exprasmlist^.concat(new(paicpu,
  2999. op_const_ref(A_MOV,S_L,0,hr)));
  3000. end;
  3001. exprasmlist^.concat(new(paicpu,
  3002. op_reg(A_PUSH,S_L,R_EAX)));
  3003. end
  3004. else
  3005. begin
  3006. getlabel(again);
  3007. getexplicitregister32(R_EDI);
  3008. exprasmlist^.concat(new(paicpu,
  3009. op_const_reg(A_MOV,S_L,stackframe div winstackpagesize,R_EDI)));
  3010. emitlab(again);
  3011. exprasmlist^.concat(new(paicpu,
  3012. op_const_reg(A_SUB,S_L,winstackpagesize-4,R_ESP)));
  3013. exprasmlist^.concat(new(paicpu,
  3014. op_reg(A_PUSH,S_L,R_EAX)));
  3015. exprasmlist^.concat(new(paicpu,
  3016. op_reg(A_DEC,S_L,R_EDI)));
  3017. emitjmp(C_NZ,again);
  3018. ungetregister32(R_EDI);
  3019. exprasmlist^.concat(new(paicpu,
  3020. op_const_reg(A_SUB,S_L,stackframe mod winstackpagesize,R_ESP)));
  3021. end
  3022. end
  3023. else
  3024. exprasmlist^.insert(new(paicpu,op_const_reg(A_SUB,S_L,stackframe,R_ESP)));
  3025. if (cs_check_stack in aktlocalswitches) and
  3026. not(target_info.target in [target_i386_freebsd,
  3027. target_i386_linux,target_i386_win32]) then
  3028. begin
  3029. emitinsertcall('FPC_STACKCHECK');
  3030. exprasmlist^.insert(new(paicpu,op_const(A_PUSH,S_L,stackframe)));
  3031. end;
  3032. if cs_profile in aktmoduleswitches then
  3033. genprofilecode;
  3034. exprasmlist^.insert(new(paicpu,op_reg_reg(A_MOV,S_L,R_ESP,R_EBP)));
  3035. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EBP)));
  3036. end;
  3037. end { endif stackframe <> 0 }
  3038. else
  3039. begin
  3040. if cs_profile in aktmoduleswitches then
  3041. genprofilecode;
  3042. exprasmlist^.insert(new(paicpu,op_reg_reg(A_MOV,S_L,R_ESP,R_EBP)));
  3043. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EBP)));
  3044. end;
  3045. end;
  3046. if (po_interrupt in aktprocsym^.definition^.procoptions) then
  3047. generate_interrupt_stackframe_entry;
  3048. { initialize return value }
  3049. if (procinfo^.returntype.def<>pdef(voiddef)) and
  3050. (procinfo^.returntype.def^.needs_inittable) and
  3051. ((procinfo^.returntype.def^.deftype<>objectdef) or
  3052. not(pobjectdef(procinfo^.returntype.def)^.is_class)) then
  3053. begin
  3054. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  3055. reset_reference(r);
  3056. r.offset:=procinfo^.return_offset;
  3057. r.base:=procinfo^.framepointer;
  3058. initialize(procinfo^.returntype.def,r,ret_in_param(procinfo^.returntype.def));
  3059. end;
  3060. { initialisize local data like ansistrings }
  3061. case aktprocsym^.definition^.proctypeoption of
  3062. potype_unitinit:
  3063. begin
  3064. { using current_module^.globalsymtable is hopefully }
  3065. { more robust than symtablestack and symtablestack^.next }
  3066. psymtable(current_module^.globalsymtable)^.foreach({$ifndef TP}@{$endif}initialize_data);
  3067. psymtable(current_module^.localsymtable)^.foreach({$ifndef TP}@{$endif}initialize_data);
  3068. end;
  3069. { units have seperate code for initilization and finalization }
  3070. potype_unitfinalize: ;
  3071. else
  3072. aktprocsym^.definition^.localst^.foreach({$ifndef TP}@{$endif}initialize_data);
  3073. end;
  3074. { generate copies of call by value parameters }
  3075. if not(po_assembler in aktprocsym^.definition^.procoptions) and
  3076. not (pocall_cdecl in aktprocsym^.definition^.proccalloptions) then
  3077. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}copyvalueparas);
  3078. { add a reference to all call by value/const parameters }
  3079. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}incr_data);
  3080. { initialisizes temp. ansi/wide string data }
  3081. inittempansistrings;
  3082. { do we need an exception frame because of ansi/widestrings ? }
  3083. if not inlined and
  3084. ((procinfo^.flags and pi_needs_implicit_finally)<>0) and
  3085. { but it's useless in init/final code of units }
  3086. not(aktprocsym^.definition^.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  3087. begin
  3088. usedinproc:=usedinproc or ($80 shr byte(R_EAX));
  3089. { Type of stack-frame must be pushed}
  3090. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,1)));
  3091. emitcall('FPC_PUSHEXCEPTADDR');
  3092. exprasmlist^.concat(new(paicpu,
  3093. op_reg(A_PUSH,S_L,R_EAX)));
  3094. emitcall('FPC_SETJMP');
  3095. exprasmlist^.concat(new(paicpu,
  3096. op_reg(A_PUSH,S_L,R_EAX)));
  3097. exprasmlist^.concat(new(paicpu,
  3098. op_reg_reg(A_TEST,S_L,R_EAX,R_EAX)));
  3099. emitjmp(C_NE,aktexitlabel);
  3100. { probably we've to reload self here }
  3101. maybe_loadesi;
  3102. end;
  3103. if not inlined then
  3104. begin
  3105. if (cs_profile in aktmoduleswitches) or
  3106. (aktprocsym^.definition^.owner^.symtabletype=globalsymtable) or
  3107. (assigned(procinfo^._class) and (procinfo^._class^.owner^.symtabletype=globalsymtable)) then
  3108. make_global:=true;
  3109. hs:=proc_names.get;
  3110. {$ifdef GDB}
  3111. if (cs_debuginfo in aktmoduleswitches) and target_os.use_function_relative_addresses then
  3112. stab_function_name := new(pai_stab_function_name,init(strpnew(hs)));
  3113. {$EndIf GDB}
  3114. while hs<>'' do
  3115. begin
  3116. if make_global then
  3117. exprasmlist^.insert(new(pai_symbol,initname_global(hs,0)))
  3118. else
  3119. exprasmlist^.insert(new(pai_symbol,initname(hs,0)));
  3120. {$ifdef GDB}
  3121. if (cs_debuginfo in aktmoduleswitches) and
  3122. target_os.use_function_relative_addresses then
  3123. exprasmlist^.insert(new(pai_stab_function_name,init(strpnew(hs))));
  3124. {$endif GDB}
  3125. hs:=proc_names.get;
  3126. end;
  3127. if make_global or ((procinfo^.flags and pi_is_global) <> 0) then
  3128. aktprocsym^.is_global := True;
  3129. {$ifdef GDB}
  3130. if (cs_debuginfo in aktmoduleswitches) then
  3131. begin
  3132. if target_os.use_function_relative_addresses then
  3133. exprasmlist^.insert(stab_function_name);
  3134. exprasmlist^.insert(new(pai_stabs,init(aktprocsym^.stabstring)));
  3135. aktprocsym^.isstabwritten:=true;
  3136. end;
  3137. {$endif GDB}
  3138. { Align, gprof uses 16 byte granularity }
  3139. if (cs_profile in aktmoduleswitches) then
  3140. exprasmlist^.insert(new(pai_align,init_op(16,$90)))
  3141. else
  3142. if not(cs_littlesize in aktglobalswitches) then
  3143. exprasmlist^.insert(new(pai_align,init(16)));
  3144. end;
  3145. if inlined then
  3146. load_regvars(exprasmlist,nil);
  3147. exprasmlist:=oldexprasmlist;
  3148. end;
  3149. procedure handle_return_value(inlined : boolean;var uses_eax,uses_edx : boolean);
  3150. var
  3151. hr : preference;
  3152. op : Tasmop;
  3153. s : Topsize;
  3154. begin
  3155. uses_eax:=false;
  3156. uses_edx:=false;
  3157. if procinfo^.returntype.def<>pdef(voiddef) then
  3158. begin
  3159. {if ((procinfo^.flags and pi_operator)<>0) and
  3160. assigned(opsym) then
  3161. procinfo^.funcret_is_valid:=
  3162. procinfo^.funcret_is_valid or (opsym^.refs>0);}
  3163. if (procinfo^.funcret_state<>vs_assigned) and not inlined { and
  3164. ((procinfo^.flags and pi_uses_asm)=0)} then
  3165. CGMessage(sym_w_function_result_not_set);
  3166. hr:=new_reference(procinfo^.framepointer,procinfo^.return_offset);
  3167. if (procinfo^.returntype.def^.deftype in [orddef,enumdef]) then
  3168. begin
  3169. uses_eax:=true;
  3170. case procinfo^.returntype.def^.size of
  3171. 8:
  3172. begin
  3173. emit_ref_reg(A_MOV,S_L,hr,R_EAX);
  3174. hr:=new_reference(procinfo^.framepointer,procinfo^.return_offset+4);
  3175. emit_ref_reg(A_MOV,S_L,hr,R_EDX);
  3176. uses_edx:=true;
  3177. end;
  3178. 4:
  3179. emit_ref_reg(A_MOV,S_L,hr,R_EAX);
  3180. 2:
  3181. emit_ref_reg(A_MOV,S_W,hr,R_AX);
  3182. 1:
  3183. emit_ref_reg(A_MOV,S_B,hr,R_AL);
  3184. end;
  3185. end
  3186. else
  3187. if ret_in_acc(procinfo^.returntype.def) then
  3188. begin
  3189. uses_eax:=true;
  3190. emit_ref_reg(A_MOV,S_L,hr,R_EAX);
  3191. end
  3192. else
  3193. if (procinfo^.returntype.def^.deftype=floatdef) then
  3194. begin
  3195. floatloadops(pfloatdef(procinfo^.returntype.def)^.typ,op,s);
  3196. exprasmlist^.concat(new(paicpu,op_ref(op,s,hr)))
  3197. end
  3198. else
  3199. dispose(hr);
  3200. end
  3201. end;
  3202. procedure genexitcode(alist : paasmoutput;parasize:longint;nostackframe,inlined:boolean);
  3203. var
  3204. {$ifdef GDB}
  3205. mangled_length : longint;
  3206. p : pchar;
  3207. {$endif GDB}
  3208. nofinal,okexitlabel,noreraiselabel,nodestroycall : pasmlabel;
  3209. hr : treference;
  3210. uses_eax,uses_edx,uses_esi : boolean;
  3211. oldexprasmlist : paasmoutput;
  3212. ai : paicpu;
  3213. pd : pprocdef;
  3214. begin
  3215. oldexprasmlist:=exprasmlist;
  3216. exprasmlist:=alist;
  3217. if aktexitlabel^.is_used then
  3218. exprasmlist^.insert(new(pai_label,init(aktexitlabel)));
  3219. { call the destructor help procedure }
  3220. if (aktprocsym^.definition^.proctypeoption=potype_destructor) and
  3221. assigned(procinfo^._class) then
  3222. begin
  3223. if procinfo^._class^.is_class then
  3224. begin
  3225. emitinsertcall('FPC_DISPOSE_CLASS');
  3226. end
  3227. else
  3228. begin
  3229. emitinsertcall('FPC_HELP_DESTRUCTOR');
  3230. getexplicitregister32(R_EDI);
  3231. exprasmlist^.insert(new(paicpu,op_const_reg(A_MOV,S_L,procinfo^._class^.vmt_offset,R_EDI)));
  3232. { must the object be finalized ? }
  3233. if procinfo^._class^.needs_inittable then
  3234. begin
  3235. getlabel(nofinal);
  3236. exprasmlist^.insert(new(pai_label,init(nofinal)));
  3237. emitinsertcall('FPC_FINALIZE');
  3238. ungetregister32(R_EDI);
  3239. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_ESI)));
  3240. exprasmlist^.insert(new(paicpu,op_sym(A_PUSH,S_L,procinfo^._class^.get_inittable_label)));
  3241. ai:=new(paicpu,op_sym(A_Jcc,S_NO,nofinal));
  3242. ai^.SetCondition(C_Z);
  3243. exprasmlist^.insert(ai);
  3244. reset_reference(hr);
  3245. hr.base:=R_EBP;
  3246. hr.offset:=8;
  3247. exprasmlist^.insert(new(paicpu,op_const_ref(A_CMP,S_L,0,newreference(hr))));
  3248. end;
  3249. end;
  3250. end;
  3251. { finalize temporary data }
  3252. finalizetempansistrings;
  3253. { finalize local data like ansistrings}
  3254. case aktprocsym^.definition^.proctypeoption of
  3255. potype_unitfinalize:
  3256. begin
  3257. { using current_module^.globalsymtable is hopefully }
  3258. { more robust than symtablestack and symtablestack^.next }
  3259. psymtable(current_module^.globalsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  3260. psymtable(current_module^.localsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  3261. end;
  3262. { units have seperate code for initialization and finalization }
  3263. potype_unitinit: ;
  3264. else
  3265. aktprocsym^.definition^.localst^.foreach({$ifndef TP}@{$endif}finalize_data);
  3266. end;
  3267. { finalize paras data }
  3268. if assigned(aktprocsym^.definition^.parast) then
  3269. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}finalize_data);
  3270. { do we need to handle exceptions because of ansi/widestrings ? }
  3271. if not inlined and
  3272. ((procinfo^.flags and pi_needs_implicit_finally)<>0) and
  3273. { but it's useless in init/final code of units }
  3274. not(aktprocsym^.definition^.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  3275. begin
  3276. { the exception helper routines modify all registers }
  3277. aktprocsym^.definition^.usedregisters:=$ff;
  3278. getlabel(noreraiselabel);
  3279. emitcall('FPC_POPADDRSTACK');
  3280. exprasmlist^.concat(new(paicpu,
  3281. op_reg(A_POP,S_L,R_EAX)));
  3282. exprasmlist^.concat(new(paicpu,
  3283. op_reg_reg(A_TEST,S_L,R_EAX,R_EAX)));
  3284. emitjmp(C_E,noreraiselabel);
  3285. if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
  3286. begin
  3287. if assigned(procinfo^._class) then
  3288. begin
  3289. pd:=procinfo^._class^.searchdestructor;
  3290. if assigned(pd) then
  3291. begin
  3292. getlabel(nodestroycall);
  3293. emit_const_ref(A_CMP,S_L,0,new_reference(procinfo^.framepointer,
  3294. procinfo^.selfpointer_offset));
  3295. emitjmp(C_E,nodestroycall);
  3296. if procinfo^._class^.is_class then
  3297. begin
  3298. emit_const(A_PUSH,S_L,1);
  3299. emit_reg(A_PUSH,S_L,R_ESI);
  3300. end
  3301. else
  3302. begin
  3303. emit_reg(A_PUSH,S_L,R_ESI);
  3304. emit_sym(A_PUSH,S_L,newasmsymbol(procinfo^._class^.vmt_mangledname));
  3305. end;
  3306. if (po_virtualmethod in pd^.procoptions) then
  3307. begin
  3308. emit_ref_reg(A_MOV,S_L,new_reference(R_ESI,0),R_EDI);
  3309. emit_ref(A_CALL,S_NO,new_reference(R_EDI,procinfo^._class^.vmtmethodoffset(pd^.extnumber)));
  3310. end
  3311. else
  3312. emitcall(pd^.mangledname);
  3313. { not necessary because the result is never assigned in the
  3314. case of an exception (FK)
  3315. emit_const_reg(A_MOV,S_L,0,R_ESI);
  3316. emit_const_ref(A_MOV,S_L,0,new_reference(procinfo^.framepointer,8));
  3317. }
  3318. emitlab(nodestroycall);
  3319. end;
  3320. end
  3321. end
  3322. else
  3323. { must be the return value finalized before reraising the exception? }
  3324. if (procinfo^.returntype.def<>pdef(voiddef)) and
  3325. (procinfo^.returntype.def^.needs_inittable) and
  3326. ((procinfo^.returntype.def^.deftype<>objectdef) or
  3327. not(pobjectdef(procinfo^.returntype.def)^.is_class)) then
  3328. begin
  3329. reset_reference(hr);
  3330. hr.offset:=procinfo^.return_offset;
  3331. hr.base:=procinfo^.framepointer;
  3332. finalize(procinfo^.returntype.def,hr,ret_in_param(procinfo^.returntype.def));
  3333. end;
  3334. emitcall('FPC_RERAISE');
  3335. emitlab(noreraiselabel);
  3336. end;
  3337. { call __EXIT for main program }
  3338. if (not DLLsource) and (not inlined) and (aktprocsym^.definition^.proctypeoption=potype_proginit) then
  3339. begin
  3340. emitcall('FPC_DO_EXIT');
  3341. end;
  3342. { handle return value }
  3343. uses_eax:=false;
  3344. uses_edx:=false;
  3345. uses_esi:=false;
  3346. if not(po_assembler in aktprocsym^.definition^.procoptions) then
  3347. if (aktprocsym^.definition^.proctypeoption<>potype_constructor) then
  3348. handle_return_value(inlined,uses_eax,uses_edx)
  3349. else
  3350. begin
  3351. { successful constructor deletes the zero flag }
  3352. { and returns self in eax }
  3353. { eax must be set to zero if the allocation failed !!! }
  3354. getlabel(okexitlabel);
  3355. emitjmp(C_NONE,okexitlabel);
  3356. emitlab(faillabel);
  3357. if procinfo^._class^.is_class then
  3358. begin
  3359. emit_ref_reg(A_MOV,S_L,new_reference(procinfo^.framepointer,8),R_ESI);
  3360. emitcall('FPC_HELP_FAIL_CLASS');
  3361. end
  3362. else
  3363. begin
  3364. emit_ref_reg(A_MOV,S_L,new_reference(procinfo^.framepointer,12),R_ESI);
  3365. getexplicitregister32(R_EDI);
  3366. emit_const_reg(A_MOV,S_L,procinfo^._class^.vmt_offset,R_EDI);
  3367. emitcall('FPC_HELP_FAIL');
  3368. ungetregister32(R_EDI);
  3369. end;
  3370. emitlab(okexitlabel);
  3371. emit_reg_reg(A_MOV,S_L,R_ESI,R_EAX);
  3372. emit_reg_reg(A_TEST,S_L,R_ESI,R_ESI);
  3373. uses_eax:=true;
  3374. uses_esi:=true;
  3375. end;
  3376. { stabs uses the label also ! }
  3377. if aktexit2label^.is_used or
  3378. ((cs_debuginfo in aktmoduleswitches) and not inlined) then
  3379. emitlab(aktexit2label);
  3380. { gives problems for long mangled names }
  3381. {list^.concat(new(pai_symbol,init(aktprocsym^.definition^.mangledname+'_end')));}
  3382. { should we restore edi ? }
  3383. { for all i386 gcc implementations }
  3384. if (po_savestdregs in aktprocsym^.definition^.procoptions) then
  3385. begin
  3386. if (aktprocsym^.definition^.usedregisters and ($80 shr byte(R_EBX)))<>0 then
  3387. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_EBX)));
  3388. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ESI)));
  3389. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_EDI)));
  3390. { here we could reset R_EBX
  3391. but that is risky because it only works
  3392. if genexitcode is called after genentrycode
  3393. so lets skip this for the moment PM
  3394. aktprocsym^.definition^.usedregisters:=
  3395. aktprocsym^.definition^.usedregisters or not ($80 shr byte(R_EBX));
  3396. }
  3397. end;
  3398. { for the save all registers we can simply use a pusha,popa which
  3399. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  3400. if (po_saveregisters in aktprocsym^.definition^.procoptions) then
  3401. begin
  3402. if uses_esi then
  3403. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_ESI,new_reference(R_ESP,4))));
  3404. if uses_edx then
  3405. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDX,new_reference(R_ESP,20))));
  3406. if uses_eax then
  3407. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EAX,new_reference(R_ESP,28))));
  3408. exprasmlist^.concat(new(paicpu,op_none(A_POPA,S_L)))
  3409. end;
  3410. if not(nostackframe) then
  3411. begin
  3412. if not inlined then
  3413. exprasmlist^.concat(new(paicpu,op_none(A_LEAVE,S_NO)));
  3414. end
  3415. else
  3416. begin
  3417. if (gettempsize<>0) and not inlined then
  3418. exprasmlist^.insert(new(paicpu,
  3419. op_const_reg(A_ADD,S_L,gettempsize,R_ESP)));
  3420. end;
  3421. { parameters are limited to 65535 bytes because }
  3422. { ret allows only imm16 }
  3423. if (parasize>65535) and not(pocall_clearstack in aktprocsym^.definition^.proccalloptions) then
  3424. CGMessage(cg_e_parasize_too_big);
  3425. { at last, the return is generated }
  3426. if not inlined then
  3427. if (po_interrupt in aktprocsym^.definition^.procoptions) then
  3428. begin
  3429. if uses_esi then
  3430. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_ESI,new_reference(R_ESP,16))));
  3431. if uses_edx then
  3432. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDX,new_reference(R_ESP,12))));
  3433. if uses_eax then
  3434. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EAX,new_reference(R_ESP,0))));
  3435. generate_interrupt_stackframe_exit;
  3436. end
  3437. else
  3438. begin
  3439. {Routines with the poclearstack flag set use only a ret.}
  3440. { also routines with parasize=0 }
  3441. if (pocall_clearstack in aktprocsym^.definition^.proccalloptions) then
  3442. begin
  3443. {$ifndef OLD_C_STACK}
  3444. { complex return values are removed from stack in C code PM }
  3445. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  3446. exprasmlist^.concat(new(paicpu,op_const(A_RET,S_NO,4)))
  3447. else
  3448. {$endif not OLD_C_STACK}
  3449. exprasmlist^.concat(new(paicpu,op_none(A_RET,S_NO)));
  3450. end
  3451. else if (parasize=0) then
  3452. exprasmlist^.concat(new(paicpu,op_none(A_RET,S_NO)))
  3453. else
  3454. exprasmlist^.concat(new(paicpu,op_const(A_RET,S_NO,parasize)));
  3455. end;
  3456. if not inlined then
  3457. exprasmlist^.concat(new(pai_symbol_end,initname(aktprocsym^.definition^.mangledname)));
  3458. {$ifdef GDB}
  3459. if (cs_debuginfo in aktmoduleswitches) and not inlined then
  3460. begin
  3461. aktprocsym^.concatstabto(exprasmlist);
  3462. if assigned(procinfo^._class) then
  3463. if (not assigned(procinfo^.parent) or
  3464. not assigned(procinfo^.parent^._class)) then
  3465. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  3466. '"$t:v'+procinfo^._class^.numberstring+'",'+
  3467. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.selfpointer_offset)))))
  3468. else
  3469. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  3470. '"$t:r*'+procinfo^._class^.numberstring+'",'+
  3471. tostr(N_RSYM)+',0,0,'+tostr(GDB_i386index[R_ESI])))));
  3472. { define calling EBP as pseudo local var PM }
  3473. { this enables test if the function is a local one !! }
  3474. if assigned(procinfo^.parent) and (lexlevel>normal_function_level) then
  3475. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  3476. '"parent_ebp:'+voidpointerdef^.numberstring+'",'+
  3477. tostr(N_LSYM)+',0,0,'+tostr(procinfo^.framepointer_offset)))));
  3478. if (pdef(aktprocsym^.definition^.rettype.def) <> pdef(voiddef)) then
  3479. begin
  3480. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  3481. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  3482. '"'+aktprocsym^.name+':X*'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  3483. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))))
  3484. else
  3485. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  3486. '"'+aktprocsym^.name+':X'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  3487. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))));
  3488. if (m_result in aktmodeswitches) then
  3489. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  3490. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  3491. '"RESULT:X*'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  3492. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))))
  3493. else
  3494. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  3495. '"RESULT:X'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  3496. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))));
  3497. end;
  3498. mangled_length:=length(aktprocsym^.definition^.mangledname);
  3499. getmem(p,2*mangled_length+50);
  3500. strpcopy(p,'192,0,0,');
  3501. strpcopy(strend(p),aktprocsym^.definition^.mangledname);
  3502. if (target_os.use_function_relative_addresses) then
  3503. begin
  3504. strpcopy(strend(p),'-');
  3505. strpcopy(strend(p),aktprocsym^.definition^.mangledname);
  3506. end;
  3507. exprasmlist^.concat(new(pai_stabn,init(strnew(p))));
  3508. {list^.concat(new(pai_stabn,init(strpnew('192,0,0,'
  3509. +aktprocsym^.definition^.mangledname))));
  3510. p[0]:='2';p[1]:='2';p[2]:='4';
  3511. strpcopy(strend(p),'_end');}
  3512. strpcopy(p,'224,0,0,'+aktexit2label^.name);
  3513. if (target_os.use_function_relative_addresses) then
  3514. begin
  3515. strpcopy(strend(p),'-');
  3516. strpcopy(strend(p),aktprocsym^.definition^.mangledname);
  3517. end;
  3518. exprasmlist^.concatlist(withdebuglist);
  3519. exprasmlist^.concat(new(pai_stabn,init(
  3520. strnew(p))));
  3521. { strpnew('224,0,0,'
  3522. +aktprocsym^.definition^.mangledname+'_end'))));}
  3523. freemem(p,2*mangled_length+50);
  3524. end;
  3525. {$endif GDB}
  3526. if inlined then
  3527. cleanup_regvars(exprasmlist);
  3528. exprasmlist:=oldexprasmlist;
  3529. end;
  3530. procedure genimplicitunitfinal(alist : paasmoutput);
  3531. begin
  3532. { using current_module^.globalsymtable is hopefully }
  3533. { more robust than symtablestack and symtablestack^.next }
  3534. psymtable(current_module^.globalsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  3535. psymtable(current_module^.localsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  3536. exprasmlist^.insert(new(pai_symbol,initname_global('FINALIZE$$'+current_module^.modulename^,0)));
  3537. exprasmlist^.insert(new(pai_symbol,initname_global(target_os.cprefix+current_module^.modulename^+'_finalize',0)));
  3538. {$ifdef GDB}
  3539. if (cs_debuginfo in aktmoduleswitches) and
  3540. target_os.use_function_relative_addresses then
  3541. exprasmlist^.insert(new(pai_stab_function_name,init(strpnew('FINALIZE$$'+current_module^.modulename^))));
  3542. {$endif GDB}
  3543. exprasmlist^.concat(new(paicpu,op_none(A_RET,S_NO)));
  3544. alist^.concatlist(exprasmlist);
  3545. end;
  3546. procedure genimplicitunitinit(alist : paasmoutput);
  3547. begin
  3548. { using current_module^.globalsymtable is hopefully }
  3549. { more robust than symtablestack and symtablestack^.next }
  3550. psymtable(current_module^.globalsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  3551. psymtable(current_module^.localsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  3552. exprasmlist^.insert(new(pai_symbol,initname_global('INIT$$'+current_module^.modulename^,0)));
  3553. exprasmlist^.insert(new(pai_symbol,initname_global(target_os.cprefix+current_module^.modulename^+'_init',0)));
  3554. {$ifdef GDB}
  3555. if (cs_debuginfo in aktmoduleswitches) and
  3556. target_os.use_function_relative_addresses then
  3557. exprasmlist^.insert(new(pai_stab_function_name,init(strpnew('INIT$$'+current_module^.modulename^))));
  3558. {$endif GDB}
  3559. exprasmlist^.concat(new(paicpu,op_none(A_RET,S_NO)));
  3560. alist^.concatlist(exprasmlist);
  3561. end;
  3562. {$ifdef test_dest_loc}
  3563. procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
  3564. begin
  3565. if (dest_loc.loc=LOC_CREGISTER) or (dest_loc.loc=LOC_REGISTER) then
  3566. begin
  3567. emit_reg_reg(A_MOV,s,reg,dest_loc.register);
  3568. set_location(p^.location,dest_loc);
  3569. in_dest_loc:=true;
  3570. end
  3571. else
  3572. if (dest_loc.loc=LOC_REFERENCE) or (dest_loc.loc=LOC_MEM) then
  3573. begin
  3574. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,s,reg,newreference(dest_loc.reference))));
  3575. set_location(p^.location,dest_loc);
  3576. in_dest_loc:=true;
  3577. end
  3578. else
  3579. internalerror(20080);
  3580. end;
  3581. {$endif test_dest_loc}
  3582. end.
  3583. {
  3584. $Log$
  3585. Revision 1.18 2000-10-10 14:55:28 jonas
  3586. * added missing regallocs for edi in emit_mov_ref_reg64 (merged)
  3587. Revision 1.17 2000/10/01 19:48:23 peter
  3588. * lot of compile updates for cg11
  3589. Revision 1.16 2000/09/30 16:08:45 peter
  3590. * more cg11 updates
  3591. Revision 1.15 2000/09/24 15:06:12 peter
  3592. * use defines.inc
  3593. Revision 1.14 2000/09/16 12:22:52 peter
  3594. * freebsd support merged
  3595. Revision 1.13 2000/08/27 16:11:49 peter
  3596. * moved some util functions from globals,cobjects to cutils
  3597. * splitted files into finput,fmodule
  3598. Revision 1.12 2000/08/24 19:07:54 peter
  3599. * don't initialize if localvarsym is set because that varsym will
  3600. already be initialized
  3601. * first initialize local data before copy of value para's (merged)
  3602. Revision 1.11 2000/08/19 20:09:33 peter
  3603. * check size after checking openarray in push_value_para (merged)
  3604. Revision 1.10 2000/08/16 13:06:06 florian
  3605. + support of 64 bit integer constants
  3606. Revision 1.9 2000/08/10 18:42:03 peter
  3607. * fixed for constants in emit_push_mem_size for go32v2 (merged)
  3608. Revision 1.8 2000/08/07 11:29:40 jonas
  3609. + emit_push_mem_size() which pushes a value in memory of a certain size
  3610. * pushsetelement() and pushvaluepara() use this new procedure, because
  3611. otherwise they could sometimes try to push data past the end of the
  3612. heap, causing a crash
  3613. (merged from fixes branch)
  3614. Revision 1.7 2000/08/03 13:17:25 jonas
  3615. + allow regvars to be used inside inlined procs, which required the
  3616. following changes:
  3617. + load regvars in genentrycode/free them in genexitcode (cgai386)
  3618. * moved all regvar related code to new regvars unit
  3619. + added pregvarinfo type to hcodegen
  3620. + added regvarinfo field to tprocinfo (symdef/symdefh)
  3621. * deallocate the regvars of the caller in secondprocinline before
  3622. inlining the called procedure and reallocate them afterwards
  3623. Revision 1.6 2000/08/02 08:05:04 jonas
  3624. * fixed web bug1087
  3625. * allocate R_ECX explicitely if it's used
  3626. (merged from fixes branch)
  3627. Revision 1.5 2000/07/27 09:25:05 jonas
  3628. * moved locflags2reg() procedure from cg386add to cgai386
  3629. + added locjump2reg() procedure to cgai386
  3630. * fixed internalerror(2002) when the result of a case expression has
  3631. LOC_JUMP
  3632. (all merged from fixes branch)
  3633. Revision 1.4 2000/07/21 15:14:02 jonas
  3634. + added is_addr field for labels, if they are only used for getting the address
  3635. (e.g. for io checks) and corresponding getaddrlabel() procedure
  3636. Revision 1.3 2000/07/13 12:08:25 michael
  3637. + patched to 1.1.0 with former 1.09patch from peter
  3638. Revision 1.2 2000/07/13 11:32:37 michael
  3639. + removed logs
  3640. }