cgai386.pas 155 KB

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