cgai386.pas 149 KB

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