cgai386.pas 150 KB

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