cgai386.pas 155 KB

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