cgai386.pas 160 KB

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