cgai386.pas 153 KB

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