cgai386.pas 140 KB

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