cgai386.pas 152 KB

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