cgai386.pas 148 KB

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