cgai386.pas 154 KB

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