cgai386.pas 152 KB

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