cgai386.pas 151 KB

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