cgai386.pas 139 KB

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