cgai386.pas 158 KB

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