cgai386.pas 149 KB

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