cgai386.pas 150 KB

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