cgai386.pas 139 KB

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