cgai386.pas 107 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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. }
  18. unit cgai386;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. cobjects,
  23. cpubase,cpuasm,
  24. symconst,symtable,aasm;
  25. {$define TESTGETTEMP to store const that
  26. are written into temps for later release PM }
  27. function def_opsize(p1:pdef):topsize;
  28. function def2def_opsize(p1,p2:pdef):topsize;
  29. function def_getreg(p1:pdef):tregister;
  30. function makereg8(r:tregister):tregister;
  31. function makereg16(r:tregister):tregister;
  32. function makereg32(r:tregister):tregister;
  33. procedure locflags2reg(var l:tlocation;opsize:topsize);
  34. procedure locjump2reg(var l:tlocation;opsize:topsize; otl, ofl: pasmlabel);
  35. procedure emitlab(var l : pasmlabel);
  36. procedure emitjmp(c : tasmcond;var l : pasmlabel);
  37. procedure emit_flag2reg(flag:tresflags;hregister:tregister);
  38. procedure emit_none(i : tasmop;s : topsize);
  39. procedure emit_const(i : tasmop;s : topsize;c : longint);
  40. procedure emit_reg(i : tasmop;s : topsize;reg : tregister);
  41. procedure emit_ref(i : tasmop;s : topsize;ref : preference);
  42. procedure emit_const_reg(i : tasmop;s : topsize;c : longint;reg : tregister);
  43. procedure emit_const_ref(i : tasmop;s : topsize;c : longint;ref : preference);
  44. procedure emit_ref_reg(i : tasmop;s : topsize;ref : preference;reg : tregister);
  45. procedure emit_reg_ref(i : tasmop;s : topsize;reg : tregister;ref : preference);
  46. procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
  47. procedure emit_const_reg_reg(i : tasmop;s : topsize;c : longint;reg1,reg2 : tregister);
  48. procedure emit_reg_reg_reg(i : tasmop;s : topsize;reg1,reg2,reg3 : tregister);
  49. procedure emit_sym(i : tasmop;s : topsize;op : pasmsymbol);
  50. procedure emit_sym_ofs(i : tasmop;s : topsize;op : pasmsymbol;ofs : longint);
  51. procedure emit_sym_ofs_reg(i : tasmop;s : topsize;op : pasmsymbol;ofs:longint;reg : tregister);
  52. procedure emit_sym_ofs_ref(i : tasmop;s : topsize;op : pasmsymbol;ofs:longint;ref : preference);
  53. procedure emitcall(const routine:string);
  54. procedure emit_mov_loc_ref(const t:tlocation;const ref:treference;siz:topsize;freetemp:boolean);
  55. procedure emit_mov_loc_reg(const t:tlocation;reg:tregister);
  56. procedure emit_mov_ref_reg64(r : treference;rl,rh : tregister);
  57. procedure emit_lea_loc_ref(const t:tlocation;const ref:treference;freetemp:boolean);
  58. procedure emit_lea_loc_reg(const t:tlocation;reg:tregister;freetemp:boolean);
  59. procedure emit_push_loc(const t:tlocation);
  60. procedure emit_push_mem_size(const t: treference; size: longint);
  61. { pushes qword location to the stack }
  62. procedure emit_pushq_loc(const t : tlocation);
  63. procedure release_qword_loc(const t : tlocation);
  64. { remove non regvar registers in loc from regs (in the format }
  65. { pushusedregisters uses) }
  66. procedure remove_non_regvars_from_loc(const t: tlocation; var regs: byte);
  67. { releases the registers of a location }
  68. procedure release_loc(const t : tlocation);
  69. procedure emit_pushw_loc(const t:tlocation);
  70. procedure emit_push_lea_loc(const t:tlocation;freetemp:boolean);
  71. procedure emit_to_mem(var t:tlocation;def:pdef);
  72. procedure emit_to_reg16(var hr:tregister);
  73. procedure emit_to_reg32(var hr:tregister);
  74. procedure emit_mov_reg_loc(reg: TRegister; const t:tlocation);
  75. procedure emit_movq_reg_loc(reghigh,reglow: TRegister;t:tlocation);
  76. procedure copyshortstring(const dref,sref : treference;len : byte;
  77. loadref, del_sref: boolean);
  78. procedure finalize(t : pdef;const ref : treference;is_already_ref : boolean);
  79. procedure incrstringref(t : pdef;const ref : treference);
  80. procedure decrstringref(t : pdef;const ref : treference);
  81. procedure push_int(l : longint);
  82. procedure emit_push_mem(const ref : treference);
  83. procedure emitpushreferenceaddr(const ref : treference);
  84. procedure floatload(t : tfloattype;const ref : treference);
  85. procedure floatstore(t : tfloattype;const ref : treference);
  86. procedure floatloadops(t : tfloattype;var op : tasmop;var s : topsize);
  87. procedure floatstoreops(t : tfloattype;var op : tasmop;var s : topsize);
  88. procedure maybe_loadesi;
  89. procedure emitloadord2reg(const location:Tlocation;orddef:Porddef;destreg:Tregister;delloc:boolean);
  90. procedure concatcopy(source,dest : treference;size : longint;delsource : boolean;loadref:boolean);
  91. procedure genentrycode(alist : paasmoutput;const proc_names:Tstringcontainer;make_global:boolean;
  92. stackframe:longint;
  93. var parasize:longint;var nostackframe:boolean;
  94. inlined : boolean);
  95. procedure genexitcode(alist : paasmoutput;parasize:longint;
  96. nostackframe,inlined:boolean);
  97. { if a unit doesn't have a explicit init/final code, }
  98. { we've to generate one, if the units has ansistrings }
  99. { in the interface or implementation }
  100. procedure genimplicitunitfinal(alist : paasmoutput);
  101. procedure genimplicitunitinit(alist : paasmoutput);
  102. {$ifdef test_dest_loc}
  103. const
  104. { used to avoid temporary assignments }
  105. dest_loc_known : boolean = false;
  106. in_dest_loc : boolean = false;
  107. dest_loc_tree : ptree = nil;
  108. var
  109. dest_loc : tlocation;
  110. procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
  111. {$endif test_dest_loc}
  112. implementation
  113. uses
  114. {$ifdef delphi}
  115. sysutils,
  116. {$else}
  117. strings,
  118. {$endif}
  119. cutils,globtype,systems,globals,verbose,fmodule,types,
  120. tgeni386,temp_gen,hcodegen,regvars
  121. {$ifdef GDB}
  122. ,gdb
  123. {$endif}
  124. {$ifndef NOTARGETWIN32}
  125. ,t_win32
  126. {$endif}
  127. ;
  128. {*****************************************************************************
  129. Helpers
  130. *****************************************************************************}
  131. function def_opsize(p1:pdef):topsize;
  132. begin
  133. case p1^.size of
  134. 1 : def_opsize:=S_B;
  135. 2 : def_opsize:=S_W;
  136. 4 : def_opsize:=S_L;
  137. else
  138. internalerror(130820001);
  139. end;
  140. end;
  141. function def2def_opsize(p1,p2:pdef):topsize;
  142. var
  143. o1 : topsize;
  144. begin
  145. case p1^.size of
  146. 1 : o1:=S_B;
  147. 2 : o1:=S_W;
  148. 4 : o1:=S_L;
  149. { I don't know if we need it (FK) }
  150. 8 : o1:=S_L;
  151. else
  152. internalerror(130820002);
  153. end;
  154. if assigned(p2) then
  155. begin
  156. case p2^.size of
  157. 1 : o1:=S_B;
  158. 2 : begin
  159. if o1=S_B then
  160. o1:=S_BW
  161. else
  162. o1:=S_W;
  163. end;
  164. 4,8:
  165. begin
  166. case o1 of
  167. S_B : o1:=S_BL;
  168. S_W : o1:=S_WL;
  169. end;
  170. end;
  171. end;
  172. end;
  173. def2def_opsize:=o1;
  174. end;
  175. function def_getreg(p1:pdef):tregister;
  176. begin
  177. case p1^.size of
  178. 1 : def_getreg:=reg32toreg8(getregister32);
  179. 2 : def_getreg:=reg32toreg16(getregister32);
  180. 4 : def_getreg:=getregister32;
  181. else
  182. internalerror(130820003);
  183. end;
  184. end;
  185. function makereg8(r:tregister):tregister;
  186. begin
  187. case r of
  188. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  189. makereg8:=reg32toreg8(r);
  190. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  191. makereg8:=reg16toreg8(r);
  192. R_AL,R_BL,R_CL,R_DL :
  193. makereg8:=r;
  194. end;
  195. end;
  196. function makereg16(r:tregister):tregister;
  197. begin
  198. case r of
  199. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  200. makereg16:=reg32toreg16(r);
  201. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  202. makereg16:=r;
  203. R_AL,R_BL,R_CL,R_DL :
  204. makereg16:=reg8toreg16(r);
  205. end;
  206. end;
  207. function makereg32(r:tregister):tregister;
  208. begin
  209. case r of
  210. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP :
  211. makereg32:=r;
  212. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP :
  213. makereg32:=reg16toreg32(r);
  214. R_AL,R_BL,R_CL,R_DL :
  215. makereg32:=reg8toreg32(r);
  216. end;
  217. end;
  218. procedure locflags2reg(var l:tlocation;opsize:topsize);
  219. var
  220. hregister : tregister;
  221. begin
  222. if (l.loc=LOC_FLAGS) then
  223. begin
  224. hregister:=getregister32;
  225. case opsize of
  226. S_W : hregister:=reg32toreg16(hregister);
  227. S_B : hregister:=reg32toreg8(hregister);
  228. end;
  229. emit_flag2reg(l.resflags,hregister);
  230. l.loc:=LOC_REGISTER;
  231. l.register:=hregister;
  232. end
  233. else internalerror(270720001);
  234. end;
  235. procedure locjump2reg(var l:tlocation;opsize:topsize; otl, ofl: pasmlabel);
  236. var
  237. hregister : tregister;
  238. hl : pasmlabel;
  239. begin
  240. if l.loc = LOC_JUMP then
  241. begin
  242. hregister:=getregister32;
  243. case opsize of
  244. S_W : hregister:=reg32toreg16(hregister);
  245. S_B : hregister:=reg32toreg8(hregister);
  246. end;
  247. l.loc:=LOC_REGISTER;
  248. l.register:=hregister;
  249. emitlab(truelabel);
  250. truelabel:=otl;
  251. emit_const_reg(A_MOV,opsize,1,hregister);
  252. getlabel(hl);
  253. emitjmp(C_None,hl);
  254. emitlab(falselabel);
  255. falselabel:=ofl;
  256. emit_reg_reg(A_XOR,S_L,makereg32(hregister),
  257. makereg32(hregister));
  258. emitlab(hl);
  259. end
  260. else internalerror(270720002);
  261. end;
  262. {*****************************************************************************
  263. Emit Assembler
  264. *****************************************************************************}
  265. procedure emitlab(var l : pasmlabel);
  266. begin
  267. if not l^.is_set then
  268. exprasmlist^.concat(new(pai_label,init(l)))
  269. else
  270. internalerror(7453984);
  271. end;
  272. procedure emitjmp(c : tasmcond;var l : pasmlabel);
  273. var
  274. ai : Paicpu;
  275. begin
  276. if c=C_None then
  277. ai := new(paicpu,op_sym(A_JMP,S_NO,l))
  278. else
  279. begin
  280. ai:=new(paicpu,op_sym(A_Jcc,S_NO,l));
  281. ai^.SetCondition(c);
  282. end;
  283. ai^.is_jmp:=true;
  284. exprasmlist^.concat(ai);
  285. end;
  286. procedure emit_flag2reg(flag:tresflags;hregister:tregister);
  287. var
  288. ai : paicpu;
  289. hreg : tregister;
  290. begin
  291. hreg:=makereg8(hregister);
  292. ai:=new(paicpu,op_reg(A_Setcc,S_B,hreg));
  293. ai^.SetCondition(flag_2_cond[flag]);
  294. exprasmlist^.concat(ai);
  295. if hreg<>hregister then
  296. begin
  297. if hregister in regset16bit then
  298. emit_to_reg16(hreg)
  299. else
  300. emit_to_reg32(hreg);
  301. end;
  302. end;
  303. procedure emit_none(i : tasmop;s : topsize);
  304. begin
  305. exprasmlist^.concat(new(paicpu,op_none(i,s)));
  306. end;
  307. procedure emit_reg(i : tasmop;s : topsize;reg : tregister);
  308. begin
  309. exprasmlist^.concat(new(paicpu,op_reg(i,s,reg)));
  310. end;
  311. procedure emit_ref(i : tasmop;s : topsize;ref : preference);
  312. begin
  313. exprasmlist^.concat(new(paicpu,op_ref(i,s,ref)));
  314. end;
  315. procedure emit_const(i : tasmop;s : topsize;c : longint);
  316. begin
  317. exprasmlist^.concat(new(paicpu,op_const(i,s,c)));
  318. end;
  319. procedure emit_const_reg(i : tasmop;s : topsize;c : longint;reg : tregister);
  320. begin
  321. exprasmlist^.concat(new(paicpu,op_const_reg(i,s,c,reg)));
  322. end;
  323. procedure emit_const_ref(i : tasmop;s : topsize;c : longint;ref : preference);
  324. begin
  325. exprasmlist^.concat(new(paicpu,op_const_ref(i,s,c,ref)));
  326. end;
  327. procedure emit_ref_reg(i : tasmop;s : topsize;ref : preference;reg : tregister);
  328. begin
  329. exprasmlist^.concat(new(paicpu,op_ref_reg(i,s,ref,reg)));
  330. end;
  331. procedure emit_reg_ref(i : tasmop;s : topsize;reg : tregister;ref : preference);
  332. begin
  333. exprasmlist^.concat(new(paicpu,op_reg_ref(i,s,reg,ref)));
  334. end;
  335. procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
  336. begin
  337. if (reg1<>reg2) or (i<>A_MOV) then
  338. exprasmlist^.concat(new(paicpu,op_reg_reg(i,s,reg1,reg2)));
  339. end;
  340. procedure emit_const_reg_reg(i : tasmop;s : topsize;c : longint;reg1,reg2 : tregister);
  341. begin
  342. exprasmlist^.concat(new(paicpu,op_const_reg_reg(i,s,c,reg1,reg2)));
  343. end;
  344. procedure emit_reg_reg_reg(i : tasmop;s : topsize;reg1,reg2,reg3 : tregister);
  345. begin
  346. exprasmlist^.concat(new(paicpu,op_reg_reg_reg(i,s,reg1,reg2,reg3)));
  347. end;
  348. procedure emit_sym(i : tasmop;s : topsize;op : pasmsymbol);
  349. begin
  350. exprasmlist^.concat(new(paicpu,op_sym(i,s,op)));
  351. end;
  352. procedure emit_sym_ofs(i : tasmop;s : topsize;op : pasmsymbol;ofs : longint);
  353. begin
  354. exprasmlist^.concat(new(paicpu,op_sym_ofs(i,s,op,ofs)));
  355. end;
  356. procedure emit_sym_ofs_reg(i : tasmop;s : topsize;op : pasmsymbol;ofs:longint;reg : tregister);
  357. begin
  358. exprasmlist^.concat(new(paicpu,op_sym_ofs_reg(i,s,op,ofs,reg)));
  359. end;
  360. procedure emit_sym_ofs_ref(i : tasmop;s : topsize;op : pasmsymbol;ofs:longint;ref : preference);
  361. begin
  362. exprasmlist^.concat(new(paicpu,op_sym_ofs_ref(i,s,op,ofs,ref)));
  363. end;
  364. procedure emitcall(const routine:string);
  365. begin
  366. exprasmlist^.concat(new(paicpu,op_sym(A_CALL,S_NO,newasmsymbol(routine))));
  367. end;
  368. { only usefull in startup code }
  369. procedure emitinsertcall(const routine:string);
  370. begin
  371. exprasmlist^.insert(new(paicpu,op_sym(A_CALL,S_NO,newasmsymbol(routine))));
  372. end;
  373. procedure emit_mov_loc_ref(const t:tlocation;const ref:treference;siz:topsize;freetemp:boolean);
  374. var
  375. hreg : tregister;
  376. pushedeax : boolean;
  377. begin
  378. pushedeax:=false;
  379. case t.loc of
  380. LOC_REGISTER,
  381. LOC_CREGISTER : begin
  382. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,siz,
  383. t.register,newreference(ref))));
  384. ungetregister32(t.register); { the register is not needed anymore }
  385. end;
  386. LOC_MEM,
  387. LOC_REFERENCE : begin
  388. if t.reference.is_immediate then
  389. emit_const_ref(A_MOV,siz,
  390. t.reference.offset,newreference(ref))
  391. else
  392. begin
  393. case siz of
  394. S_B : begin
  395. { we can't do a getregister in the code generator }
  396. { without problems!!! }
  397. if usablereg32>0 then
  398. hreg:=reg32toreg8(getregister32)
  399. else
  400. begin
  401. emit_reg(A_PUSH,S_L,R_EAX);
  402. pushedeax:=true;
  403. hreg:=R_AL;
  404. end;
  405. end;
  406. S_W : hreg:=R_DI;
  407. S_L : hreg:=R_EDI;
  408. end;
  409. if hreg in [R_DI,R_EDI] then
  410. getexplicitregister32(R_EDI);
  411. emit_ref_reg(A_MOV,siz,
  412. newreference(t.reference),hreg);
  413. del_reference(t.reference);
  414. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,siz,
  415. hreg,newreference(ref))));
  416. if siz=S_B then
  417. begin
  418. if pushedeax then
  419. emit_reg(A_POP,S_L,R_EAX)
  420. else
  421. ungetregister(hreg);
  422. end;
  423. if hreg in [R_DI,R_EDI] then
  424. ungetregister32(R_EDI);
  425. { we can release the registers }
  426. { but only AFTER the MOV! Important for the optimizer!
  427. (JM)}
  428. del_reference(ref);
  429. end;
  430. if freetemp then
  431. ungetiftemp(t.reference);
  432. end;
  433. else
  434. internalerror(330);
  435. end;
  436. end;
  437. procedure emit_mov_loc_reg(const t:tlocation;reg:tregister);
  438. begin
  439. case t.loc of
  440. LOC_REGISTER,
  441. LOC_CREGISTER : begin
  442. emit_reg_reg(A_MOV,S_L,t.register,reg);
  443. ungetregister32(t.register); { the register is not needed anymore }
  444. end;
  445. LOC_MEM,
  446. LOC_REFERENCE : begin
  447. if t.reference.is_immediate then
  448. emit_const_reg(A_MOV,S_L,
  449. t.reference.offset,reg)
  450. else
  451. begin
  452. emit_ref_reg(A_MOV,S_L,
  453. newreference(t.reference),reg);
  454. end;
  455. end;
  456. else
  457. internalerror(330);
  458. end;
  459. end;
  460. procedure emit_mov_reg_loc(reg: TRegister; const t:tlocation);
  461. begin
  462. case t.loc of
  463. LOC_REGISTER,
  464. LOC_CREGISTER : begin
  465. emit_reg_reg(A_MOV,RegSize(Reg),
  466. reg,t.register);
  467. end;
  468. LOC_MEM,
  469. LOC_REFERENCE : begin
  470. if t.reference.is_immediate then
  471. internalerror(334)
  472. else
  473. begin
  474. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,RegSize(Reg),
  475. Reg,newreference(t.reference))));
  476. end;
  477. end;
  478. else
  479. internalerror(330);
  480. end;
  481. end;
  482. procedure emit_lea_loc_reg(const t:tlocation;reg:tregister;freetemp:boolean);
  483. begin
  484. case t.loc of
  485. LOC_MEM,
  486. LOC_REFERENCE : begin
  487. if t.reference.is_immediate then
  488. internalerror(331)
  489. else
  490. begin
  491. emit_ref_reg(A_LEA,S_L,
  492. newreference(t.reference),reg);
  493. end;
  494. if freetemp then
  495. ungetiftemp(t.reference);
  496. end;
  497. else
  498. internalerror(332);
  499. end;
  500. end;
  501. procedure emit_movq_reg_loc(reghigh,reglow: TRegister;t:tlocation);
  502. begin
  503. case t.loc of
  504. LOC_REGISTER,
  505. LOC_CREGISTER : begin
  506. emit_reg_reg(A_MOV,S_L,
  507. reglow,t.registerlow);
  508. emit_reg_reg(A_MOV,S_L,
  509. reghigh,t.registerhigh);
  510. end;
  511. LOC_MEM,
  512. LOC_REFERENCE : begin
  513. if t.reference.is_immediate then
  514. internalerror(334)
  515. else
  516. begin
  517. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  518. Reglow,newreference(t.reference))));
  519. inc(t.reference.offset,4);
  520. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  521. Reghigh,newreference(t.reference))));
  522. end;
  523. end;
  524. else
  525. internalerror(330);
  526. end;
  527. end;
  528. procedure emit_pushq_loc(const t : tlocation);
  529. var
  530. hr : preference;
  531. begin
  532. case t.loc of
  533. LOC_REGISTER,
  534. LOC_CREGISTER:
  535. begin
  536. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,
  537. t.registerhigh)));
  538. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,
  539. t.registerlow)));
  540. end;
  541. LOC_MEM,
  542. LOC_REFERENCE:
  543. begin
  544. hr:=newreference(t.reference);
  545. inc(hr^.offset,4);
  546. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,
  547. hr)));
  548. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,
  549. newreference(t.reference))));
  550. ungetiftemp(t.reference);
  551. end;
  552. else internalerror(331);
  553. end;
  554. end;
  555. procedure remove_non_regvars_from_loc(const t: tlocation; var regs: byte);
  556. begin
  557. case t.loc of
  558. LOC_REGISTER:
  559. { can't be a regvar, since it would be LOC_CREGISTER then }
  560. regs := regs and not($80 shr byte(t.register));
  561. LOC_MEM,LOC_REFERENCE:
  562. begin
  563. if not(cs_regalloc in aktglobalswitches) or
  564. (t.reference.base in usableregs) then
  565. regs := regs and
  566. not($80 shr byte(t.reference.base));
  567. if not(cs_regalloc in aktglobalswitches) or
  568. (t.reference.index in usableregs) then
  569. regs := regs and
  570. not($80 shr byte(t.reference.index));
  571. end;
  572. end;
  573. end;
  574. procedure release_loc(const t : tlocation);
  575. begin
  576. case t.loc of
  577. LOC_REGISTER,
  578. LOC_CREGISTER:
  579. begin
  580. ungetregister32(t.register);
  581. end;
  582. LOC_MEM,
  583. LOC_REFERENCE:
  584. del_reference(t.reference);
  585. else internalerror(332);
  586. end;
  587. end;
  588. procedure release_qword_loc(const t : tlocation);
  589. begin
  590. case t.loc of
  591. LOC_REGISTER,
  592. LOC_CREGISTER:
  593. begin
  594. ungetregister32(t.registerhigh);
  595. ungetregister32(t.registerlow);
  596. end;
  597. LOC_MEM,
  598. LOC_REFERENCE:
  599. del_reference(t.reference);
  600. else internalerror(331);
  601. end;
  602. end;
  603. procedure emit_push_loc(const t:tlocation);
  604. begin
  605. case t.loc of
  606. LOC_REGISTER,
  607. LOC_CREGISTER : begin
  608. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,makereg32(t.register))));
  609. ungetregister(t.register); { the register is not needed anymore }
  610. end;
  611. LOC_MEM,
  612. LOC_REFERENCE : begin
  613. if t.reference.is_immediate then
  614. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,t.reference.offset)))
  615. else
  616. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,newreference(t.reference))));
  617. del_reference(t.reference);
  618. ungetiftemp(t.reference);
  619. end;
  620. else
  621. internalerror(330);
  622. end;
  623. end;
  624. procedure emit_pushw_loc(const t:tlocation);
  625. var
  626. opsize : topsize;
  627. begin
  628. case t.loc of
  629. LOC_REGISTER,
  630. LOC_CREGISTER : begin
  631. if target_os.stackalignment=4 then
  632. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,makereg32(t.register))))
  633. else
  634. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_W,makereg16(t.register))));
  635. ungetregister(t.register); { the register is not needed anymore }
  636. end;
  637. LOC_MEM,
  638. LOC_REFERENCE : begin
  639. if target_os.stackalignment=4 then
  640. opsize:=S_L
  641. else
  642. opsize:=S_W;
  643. if t.reference.is_immediate then
  644. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,opsize,t.reference.offset)))
  645. else
  646. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,opsize,newreference(t.reference))));
  647. del_reference(t.reference);
  648. ungetiftemp(t.reference);
  649. end;
  650. else
  651. internalerror(330);
  652. end;
  653. end;
  654. procedure emit_lea_loc_ref(const t:tlocation;const ref:treference;freetemp:boolean);
  655. begin
  656. case t.loc of
  657. LOC_MEM,
  658. LOC_REFERENCE : begin
  659. if t.reference.is_immediate then
  660. internalerror(331)
  661. else
  662. begin
  663. getexplicitregister32(R_EDI);
  664. emit_ref_reg(A_LEA,S_L,
  665. newreference(t.reference),R_EDI);
  666. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,
  667. R_EDI,newreference(ref))));
  668. ungetregister32(R_EDI);
  669. end;
  670. { release the registers }
  671. del_reference(t.reference);
  672. if freetemp then
  673. ungetiftemp(t.reference);
  674. end;
  675. else
  676. internalerror(332);
  677. end;
  678. end;
  679. procedure emit_push_lea_loc(const t:tlocation;freetemp:boolean);
  680. begin
  681. case t.loc of
  682. LOC_MEM,
  683. LOC_REFERENCE : begin
  684. if t.reference.is_immediate then
  685. internalerror(331)
  686. else
  687. begin
  688. getexplicitregister32(R_EDI);
  689. emit_ref_reg(A_LEA,S_L,
  690. newreference(t.reference),R_EDI);
  691. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  692. ungetregister32(R_EDI);
  693. end;
  694. if freetemp then
  695. ungetiftemp(t.reference);
  696. end;
  697. else
  698. internalerror(332);
  699. end;
  700. end;
  701. procedure emit_push_mem_size(const t: treference; size: longint);
  702. var
  703. s: topsize;
  704. begin
  705. if t.is_immediate then
  706. begin
  707. if (size=4) or
  708. (target_os.stackalignment=4) then
  709. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,t.offset)))
  710. else
  711. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_W,t.offset)));
  712. end
  713. else
  714. if size < 4 then
  715. begin
  716. getexplicitregister32(R_EDI);
  717. case size of
  718. 1: s := S_BL;
  719. 2: s := S_WL;
  720. else internalerror(200008071);
  721. end;
  722. exprasmlist^.concat(new(paicpu,op_ref_reg(A_MOVZX,s,
  723. newreference(t),R_EDI)));
  724. if target_os.stackalignment=4 then
  725. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)))
  726. else
  727. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_W,R_DI)));
  728. ungetregister32(R_EDI);
  729. end
  730. else
  731. if size = 4 then
  732. emit_push_mem(t)
  733. else
  734. internalerror(200008072);
  735. end;
  736. procedure emit_to_mem(var t:tlocation;def:pdef);
  737. var
  738. r : treference;
  739. begin
  740. case t.loc of
  741. LOC_FPU : begin
  742. reset_reference(t.reference);
  743. gettempofsizereference(10,t.reference);
  744. floatstore(pfloatdef(def)^.typ,t.reference);
  745. end;
  746. LOC_REGISTER:
  747. begin
  748. if is_64bitint(def) then
  749. begin
  750. gettempofsizereference(8,r);
  751. emit_reg_ref(A_MOV,S_L,t.registerlow,newreference(r));
  752. inc(r.offset,4);
  753. emit_reg_ref(A_MOV,S_L,t.registerhigh,newreference(r));
  754. dec(r.offset,4);
  755. t.reference:=r;
  756. end
  757. else
  758. internalerror(1405001);
  759. end;
  760. LOC_MEM,
  761. LOC_REFERENCE : ;
  762. LOC_CFPUREGISTER : begin
  763. emit_reg(A_FLD,S_NO,correct_fpuregister(t.register,fpuvaroffset));
  764. inc(fpuvaroffset);
  765. reset_reference(t.reference);
  766. gettempofsizereference(10,t.reference);
  767. floatstore(pfloatdef(def)^.typ,t.reference);
  768. end;
  769. else
  770. internalerror(333);
  771. end;
  772. t.loc:=LOC_MEM;
  773. end;
  774. procedure emit_to_reg16(var hr:tregister);
  775. begin
  776. { ranges are a little bit bug sensitive ! }
  777. case hr of
  778. R_EAX,R_EBX,R_ECX,R_EDX,R_EDI,R_ESI,R_ESP,R_EBP:
  779. begin
  780. hr:=reg32toreg16(hr);
  781. end;
  782. R_AL,R_BL,R_CL,R_DL:
  783. begin
  784. hr:=reg8toreg16(hr);
  785. emit_const_reg(A_AND,S_W,$ff,hr);
  786. end;
  787. R_AH,R_BH,R_CH,R_DH:
  788. begin
  789. hr:=reg8toreg16(hr);
  790. emit_const_reg(A_AND,S_W,$ff00,hr);
  791. end;
  792. end;
  793. end;
  794. procedure emit_to_reg32(var hr:tregister);
  795. begin
  796. { ranges are a little bit bug sensitive ! }
  797. case hr of
  798. R_AX,R_BX,R_CX,R_DX,R_DI,R_SI,R_SP,R_BP:
  799. begin
  800. hr:=reg16toreg32(hr);
  801. emit_const_reg(A_AND,S_L,$ffff,hr);
  802. end;
  803. R_AL,R_BL,R_CL,R_DL:
  804. begin
  805. hr:=reg8toreg32(hr);
  806. emit_const_reg(A_AND,S_L,$ff,hr);
  807. end;
  808. R_AH,R_BH,R_CH,R_DH:
  809. begin
  810. hr:=reg8toreg32(hr);
  811. emit_const_reg(A_AND,S_L,$ff00,hr);
  812. end;
  813. end;
  814. end;
  815. procedure emit_mov_ref_reg64(r : treference;rl,rh : tregister);
  816. var
  817. hr : preference;
  818. begin
  819. { if we load a 64 bit reference, we must be careful because }
  820. { we could overwrite the registers of the reference by }
  821. { accident }
  822. getexplicitregister32(R_EDI);
  823. if r.base=rl then
  824. begin
  825. emit_reg_reg(A_MOV,S_L,r.base,
  826. R_EDI);
  827. r.base:=R_EDI;
  828. end
  829. else if r.index=rl then
  830. begin
  831. emit_reg_reg(A_MOV,S_L,r.index,
  832. R_EDI);
  833. r.index:=R_EDI;
  834. end;
  835. emit_ref_reg(A_MOV,S_L,
  836. newreference(r),rl);
  837. hr:=newreference(r);
  838. inc(hr^.offset,4);
  839. emit_ref_reg(A_MOV,S_L,
  840. hr,rh);
  841. ungetregister32(R_EDI);
  842. end;
  843. {*****************************************************************************
  844. Emit String Functions
  845. *****************************************************************************}
  846. procedure copyshortstring(const dref,sref : treference;len : byte;
  847. loadref, del_sref: boolean);
  848. begin
  849. emitpushreferenceaddr(dref);
  850. { if it's deleted right before it's used, the optimizer can move }
  851. { the reg deallocations to the right places (JM) }
  852. if del_sref then
  853. del_reference(sref);
  854. if loadref then
  855. emit_push_mem(sref)
  856. else
  857. emitpushreferenceaddr(sref);
  858. push_int(len);
  859. emitcall('FPC_SHORTSTR_COPY');
  860. maybe_loadesi;
  861. end;
  862. procedure copylongstring(const dref,sref : treference;len : longint;loadref:boolean);
  863. begin
  864. emitpushreferenceaddr(dref);
  865. if loadref then
  866. emit_push_mem(sref)
  867. else
  868. emitpushreferenceaddr(sref);
  869. push_int(len);
  870. emitcall('FPC_LONGSTR_COPY');
  871. maybe_loadesi;
  872. end;
  873. procedure incrstringref(t : pdef;const ref : treference);
  874. var
  875. pushedregs : tpushed;
  876. begin
  877. pushusedregisters(pushedregs,$ff);
  878. emitpushreferenceaddr(ref);
  879. if is_ansistring(t) then
  880. begin
  881. emitcall('FPC_ANSISTR_INCR_REF');
  882. end
  883. else if is_widestring(t) then
  884. begin
  885. emitcall('FPC_WIDESTR_INCR_REF');
  886. end
  887. else internalerror(1859);
  888. popusedregisters(pushedregs);
  889. end;
  890. procedure decrstringref(t : pdef;const ref : treference);
  891. var
  892. pushedregs : tpushed;
  893. begin
  894. pushusedregisters(pushedregs,$ff);
  895. emitpushreferenceaddr(ref);
  896. if is_ansistring(t) then
  897. begin
  898. emitcall('FPC_ANSISTR_DECR_REF');
  899. end
  900. else if is_widestring(t) then
  901. begin
  902. emitcall('FPC_WIDESTR_DECR_REF');
  903. end
  904. else internalerror(1859);
  905. popusedregisters(pushedregs);
  906. end;
  907. {*****************************************************************************
  908. Emit Push Functions
  909. *****************************************************************************}
  910. procedure push_int(l : longint);
  911. begin
  912. if (l = 0) and
  913. not(aktoptprocessor in [Class386, ClassP6]) and
  914. not(cs_littlesize in aktglobalswitches)
  915. Then
  916. begin
  917. getexplicitregister32(R_EDI);
  918. emit_reg_reg(A_XOR,S_L,R_EDI,R_EDI);
  919. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  920. ungetregister32(R_EDI);
  921. end
  922. else
  923. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,l)));
  924. end;
  925. procedure emit_push_mem(const ref : treference);
  926. begin
  927. if ref.is_immediate then
  928. push_int(ref.offset)
  929. else
  930. begin
  931. if not(aktoptprocessor in [Class386, ClassP6]) and
  932. not(cs_littlesize in aktglobalswitches)
  933. then
  934. begin
  935. getexplicitregister32(R_EDI);
  936. emit_ref_reg(A_MOV,S_L,newreference(ref),R_EDI);
  937. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  938. ungetregister32(R_EDI);
  939. end
  940. else exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,newreference(ref))));
  941. end;
  942. end;
  943. procedure emitpushreferenceaddr(const ref : treference);
  944. var
  945. href : treference;
  946. begin
  947. { this will fail for references to other segments !!! }
  948. if ref.is_immediate then
  949. { is this right ? }
  950. begin
  951. { push_int(ref.offset)}
  952. gettempofsizereference(4,href);
  953. emit_const_ref(A_MOV,S_L,ref.offset,newreference(href));
  954. emitpushreferenceaddr(href);
  955. del_reference(href);
  956. end
  957. else
  958. begin
  959. if ref.segment<>R_NO then
  960. CGMessage(cg_e_cant_use_far_pointer_there);
  961. if (ref.base=R_NO) and (ref.index=R_NO) then
  962. exprasmlist^.concat(new(paicpu,op_sym_ofs(A_PUSH,S_L,ref.symbol,ref.offset)))
  963. else if (ref.base=R_NO) and (ref.index<>R_NO) and
  964. (ref.offset=0) and (ref.scalefactor=0) and (ref.symbol=nil) then
  965. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,ref.index)))
  966. else if (ref.base<>R_NO) and (ref.index=R_NO) and
  967. (ref.offset=0) and (ref.symbol=nil) then
  968. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,ref.base)))
  969. else
  970. begin
  971. getexplicitregister32(R_EDI);
  972. emit_ref_reg(A_LEA,S_L,newreference(ref),R_EDI);
  973. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  974. ungetregister32(R_EDI);
  975. end;
  976. end;
  977. end;
  978. {*****************************************************************************
  979. Emit Float Functions
  980. *****************************************************************************}
  981. procedure floatloadops(t : tfloattype;var op : tasmop;var s : topsize);
  982. begin
  983. case t of
  984. s32real : begin
  985. op:=A_FLD;
  986. s:=S_FS;
  987. end;
  988. s64real : begin
  989. op:=A_FLD;
  990. { ???? }
  991. s:=S_FL;
  992. end;
  993. s80real : begin
  994. op:=A_FLD;
  995. s:=S_FX;
  996. end;
  997. s64comp : begin
  998. op:=A_FILD;
  999. s:=S_IQ;
  1000. end;
  1001. else internalerror(17);
  1002. end;
  1003. end;
  1004. procedure floatload(t : tfloattype;const ref : treference);
  1005. var
  1006. op : tasmop;
  1007. s : topsize;
  1008. begin
  1009. floatloadops(t,op,s);
  1010. exprasmlist^.concat(new(paicpu,op_ref(op,s,
  1011. newreference(ref))));
  1012. inc(fpuvaroffset);
  1013. end;
  1014. procedure floatstoreops(t : tfloattype;var op : tasmop;var s : topsize);
  1015. begin
  1016. case t of
  1017. s32real : begin
  1018. op:=A_FSTP;
  1019. s:=S_FS;
  1020. end;
  1021. s64real : begin
  1022. op:=A_FSTP;
  1023. s:=S_FL;
  1024. end;
  1025. s80real : begin
  1026. op:=A_FSTP;
  1027. s:=S_FX;
  1028. end;
  1029. s64comp : begin
  1030. op:=A_FISTP;
  1031. s:=S_IQ;
  1032. end;
  1033. else
  1034. internalerror(17);
  1035. end;
  1036. end;
  1037. procedure floatstore(t : tfloattype;const ref : treference);
  1038. var
  1039. op : tasmop;
  1040. s : topsize;
  1041. begin
  1042. floatstoreops(t,op,s);
  1043. exprasmlist^.concat(new(paicpu,op_ref(op,s,
  1044. newreference(ref))));
  1045. dec(fpuvaroffset);
  1046. end;
  1047. {*****************************************************************************
  1048. Emit Functions
  1049. *****************************************************************************}
  1050. procedure concatcopy(source,dest : treference;size : longint;delsource,loadref : boolean);
  1051. const
  1052. isizes : array[0..3] of topsize=(S_L,S_B,S_W,S_B);
  1053. ishr : array[0..3] of byte=(2,0,1,0);
  1054. var
  1055. ecxpushed : boolean;
  1056. helpsize : longint;
  1057. i : byte;
  1058. reg8,reg32 : tregister;
  1059. swap : boolean;
  1060. procedure maybepushecx;
  1061. begin
  1062. if not(R_ECX in unused) then
  1063. begin
  1064. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,R_ECX)));
  1065. ecxpushed:=true;
  1066. end
  1067. else getexplicitregister32(R_ECX);
  1068. end;
  1069. begin
  1070. {$IfNDef regallocfix}
  1071. If delsource then
  1072. del_reference(source);
  1073. {$EndIf regallocfix}
  1074. if (not loadref) and
  1075. ((size<=8) or
  1076. (not(cs_littlesize in aktglobalswitches ) and (size<=12))) then
  1077. begin
  1078. helpsize:=size shr 2;
  1079. getexplicitregister32(R_EDI);
  1080. for i:=1 to helpsize do
  1081. begin
  1082. emit_ref_reg(A_MOV,S_L,newreference(source),R_EDI);
  1083. {$ifdef regallocfix}
  1084. If (size = 4) and delsource then
  1085. del_reference(source);
  1086. {$endif regallocfix}
  1087. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDI,newreference(dest))));
  1088. inc(source.offset,4);
  1089. inc(dest.offset,4);
  1090. dec(size,4);
  1091. end;
  1092. if size>1 then
  1093. begin
  1094. emit_ref_reg(A_MOV,S_W,newreference(source),R_DI);
  1095. {$ifdef regallocfix}
  1096. If (size = 2) and delsource then
  1097. del_reference(source);
  1098. {$endif regallocfix}
  1099. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_W,R_DI,newreference(dest))));
  1100. inc(source.offset,2);
  1101. inc(dest.offset,2);
  1102. dec(size,2);
  1103. end;
  1104. ungetregister32(R_EDI);
  1105. if size>0 then
  1106. begin
  1107. { and now look for an 8 bit register }
  1108. swap:=false;
  1109. if R_EAX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EAX))
  1110. else if R_EDX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EDX))
  1111. else if R_EBX in unused then reg8:=reg32toreg8(getexplicitregister32(R_EBX))
  1112. else if R_ECX in unused then reg8:=reg32toreg8(getexplicitregister32(R_ECX))
  1113. else
  1114. begin
  1115. swap:=true;
  1116. { we need only to check 3 registers, because }
  1117. { one is always not index or base }
  1118. if (dest.base<>R_EAX) and (dest.index<>R_EAX) then
  1119. begin
  1120. reg8:=R_AL;
  1121. reg32:=R_EAX;
  1122. end
  1123. else if (dest.base<>R_EBX) and (dest.index<>R_EBX) then
  1124. begin
  1125. reg8:=R_BL;
  1126. reg32:=R_EBX;
  1127. end
  1128. else if (dest.base<>R_ECX) and (dest.index<>R_ECX) then
  1129. begin
  1130. reg8:=R_CL;
  1131. reg32:=R_ECX;
  1132. end;
  1133. end;
  1134. if swap then
  1135. { was earlier XCHG, of course nonsense }
  1136. begin
  1137. getexplicitregister32(R_EDI);
  1138. emit_reg_reg(A_MOV,S_L,reg32,R_EDI);
  1139. end;
  1140. emit_ref_reg(A_MOV,S_B,newreference(source),reg8);
  1141. {$ifdef regallocfix}
  1142. If delsource then
  1143. del_reference(source);
  1144. {$endif regallocfix}
  1145. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_B,reg8,newreference(dest))));
  1146. if swap then
  1147. begin
  1148. emit_reg_reg(A_MOV,S_L,R_EDI,reg32);
  1149. ungetregister32(R_EDI);
  1150. end
  1151. else
  1152. ungetregister(reg8);
  1153. end;
  1154. end
  1155. else
  1156. begin
  1157. getexplicitregister32(R_EDI);
  1158. emit_ref_reg(A_LEA,S_L,newreference(dest),R_EDI);
  1159. {$ifdef regallocfix}
  1160. {is this ok?? (JM)}
  1161. del_reference(dest);
  1162. {$endif regallocfix}
  1163. exprasmlist^.concat(new(pairegalloc,alloc(R_ESI)));
  1164. if loadref then
  1165. emit_ref_reg(A_MOV,S_L,newreference(source),R_ESI)
  1166. else
  1167. begin
  1168. emit_ref_reg(A_LEA,S_L,newreference(source),R_ESI);
  1169. {$ifdef regallocfix}
  1170. if delsource then
  1171. del_reference(source);
  1172. {$endif regallocfix}
  1173. end;
  1174. exprasmlist^.concat(new(paicpu,op_none(A_CLD,S_NO)));
  1175. ecxpushed:=false;
  1176. if cs_littlesize in aktglobalswitches then
  1177. begin
  1178. maybepushecx;
  1179. emit_const_reg(A_MOV,S_L,size,R_ECX);
  1180. exprasmlist^.concat(new(paicpu,op_none(A_REP,S_NO)));
  1181. exprasmlist^.concat(new(paicpu,op_none(A_MOVSB,S_NO)));
  1182. end
  1183. else
  1184. begin
  1185. helpsize:=size shr 2;
  1186. size:=size and 3;
  1187. if helpsize>1 then
  1188. begin
  1189. maybepushecx;
  1190. emit_const_reg(A_MOV,S_L,helpsize,R_ECX);
  1191. exprasmlist^.concat(new(paicpu,op_none(A_REP,S_NO)));
  1192. end;
  1193. if helpsize>0 then
  1194. exprasmlist^.concat(new(paicpu,op_none(A_MOVSD,S_NO)));
  1195. if size>1 then
  1196. begin
  1197. dec(size,2);
  1198. exprasmlist^.concat(new(paicpu,op_none(A_MOVSW,S_NO)));
  1199. end;
  1200. if size=1 then
  1201. exprasmlist^.concat(new(paicpu,op_none(A_MOVSB,S_NO)));
  1202. end;
  1203. ungetregister32(R_EDI);
  1204. exprasmlist^.concat(new(pairegalloc,dealloc(R_ESI)));
  1205. if ecxpushed then
  1206. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ECX)))
  1207. else
  1208. ungetregister32(R_ECX);
  1209. { loading SELF-reference again }
  1210. maybe_loadesi;
  1211. end;
  1212. if delsource then
  1213. ungetiftemp(source);
  1214. end;
  1215. procedure emitloadord2reg(const location:Tlocation;orddef:Porddef;
  1216. destreg:Tregister;delloc:boolean);
  1217. {A lot smaller and less bug sensitive than the original unfolded loads.}
  1218. var tai:Paicpu;
  1219. r:Preference;
  1220. begin
  1221. tai := nil;
  1222. case location.loc of
  1223. LOC_REGISTER,LOC_CREGISTER:
  1224. begin
  1225. case orddef^.typ of
  1226. u8bit:
  1227. tai:=new(paicpu,op_reg_reg(A_MOVZX,S_BL,location.register,destreg));
  1228. s8bit:
  1229. tai:=new(paicpu,op_reg_reg(A_MOVSX,S_BL,location.register,destreg));
  1230. u16bit:
  1231. tai:=new(paicpu,op_reg_reg(A_MOVZX,S_WL,location.register,destreg));
  1232. s16bit:
  1233. tai:=new(paicpu,op_reg_reg(A_MOVSX,S_WL,location.register,destreg));
  1234. u32bit,s32bit:
  1235. if location.register <> destreg then
  1236. tai:=new(paicpu,op_reg_reg(A_MOV,S_L,location.register,destreg));
  1237. end;
  1238. if delloc then
  1239. ungetregister(location.register);
  1240. end;
  1241. LOC_MEM,
  1242. LOC_REFERENCE:
  1243. begin
  1244. if location.reference.is_immediate then
  1245. tai:=new(paicpu,op_const_reg(A_MOV,S_L,location.reference.offset,destreg))
  1246. else
  1247. begin
  1248. r:=newreference(location.reference);
  1249. case orddef^.typ of
  1250. u8bit:
  1251. tai:=new(paicpu,op_ref_reg(A_MOVZX,S_BL,r,destreg));
  1252. s8bit:
  1253. tai:=new(paicpu,op_ref_reg(A_MOVSX,S_BL,r,destreg));
  1254. u16bit:
  1255. tai:=new(paicpu,op_ref_reg(A_MOVZX,S_WL,r,destreg));
  1256. s16bit:
  1257. tai:=new(paicpu,op_ref_reg(A_MOVSX,S_WL,r,destreg));
  1258. u32bit:
  1259. tai:=new(paicpu,op_ref_reg(A_MOV,S_L,r,destreg));
  1260. s32bit:
  1261. tai:=new(paicpu,op_ref_reg(A_MOV,S_L,r,destreg));
  1262. end;
  1263. end;
  1264. if delloc then
  1265. del_reference(location.reference);
  1266. end
  1267. else
  1268. internalerror(6);
  1269. end;
  1270. if assigned(tai) then
  1271. exprasmlist^.concat(tai);
  1272. end;
  1273. { if necessary ESI is reloaded after a call}
  1274. procedure maybe_loadesi;
  1275. var
  1276. hp : preference;
  1277. p : pprocinfo;
  1278. i : longint;
  1279. begin
  1280. if assigned(procinfo^._class) then
  1281. begin
  1282. exprasmlist^.concat(new(pairegalloc,alloc(R_ESI)));
  1283. if lexlevel>normal_function_level then
  1284. begin
  1285. new(hp);
  1286. reset_reference(hp^);
  1287. hp^.offset:=procinfo^.framepointer_offset;
  1288. hp^.base:=procinfo^.framepointer;
  1289. emit_ref_reg(A_MOV,S_L,hp,R_ESI);
  1290. p:=procinfo^.parent;
  1291. for i:=3 to lexlevel-1 do
  1292. begin
  1293. new(hp);
  1294. reset_reference(hp^);
  1295. hp^.offset:=p^.framepointer_offset;
  1296. hp^.base:=R_ESI;
  1297. emit_ref_reg(A_MOV,S_L,hp,R_ESI);
  1298. p:=p^.parent;
  1299. end;
  1300. new(hp);
  1301. reset_reference(hp^);
  1302. hp^.offset:=p^.selfpointer_offset;
  1303. hp^.base:=R_ESI;
  1304. emit_ref_reg(A_MOV,S_L,hp,R_ESI);
  1305. end
  1306. else
  1307. begin
  1308. new(hp);
  1309. reset_reference(hp^);
  1310. hp^.offset:=procinfo^.selfpointer_offset;
  1311. hp^.base:=procinfo^.framepointer;
  1312. emit_ref_reg(A_MOV,S_L,hp,R_ESI);
  1313. end;
  1314. end;
  1315. end;
  1316. {*****************************************************************************
  1317. Entry/Exit Code Functions
  1318. *****************************************************************************}
  1319. procedure genprofilecode;
  1320. var
  1321. pl : pasmlabel;
  1322. begin
  1323. if (po_assembler in aktprocsym^.definition^.procoptions) then
  1324. exit;
  1325. case target_info.target of
  1326. target_i386_freebsd,
  1327. target_i386_linux:
  1328. begin
  1329. getaddrlabel(pl);
  1330. emitcall('mcount');
  1331. exprasmlist^.insert(new(paicpu,op_sym_ofs_reg(A_MOV,S_L,pl,0,R_EDX)));
  1332. exprasmlist^.insert(new(pai_section,init(sec_code)));
  1333. exprasmlist^.insert(new(pai_const,init_32bit(0)));
  1334. exprasmlist^.insert(new(pai_label,init(pl)));
  1335. exprasmlist^.insert(new(pai_align,init(4)));
  1336. exprasmlist^.insert(new(pai_section,init(sec_data)));
  1337. end;
  1338. target_i386_go32v2:
  1339. begin
  1340. emitinsertcall('MCOUNT');
  1341. end;
  1342. end;
  1343. end;
  1344. procedure generate_interrupt_stackframe_entry;
  1345. begin
  1346. { save the registers of an interrupt procedure }
  1347. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EAX)));
  1348. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EBX)));
  1349. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_ECX)));
  1350. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EDX)));
  1351. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_ESI)));
  1352. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  1353. { .... also the segment registers }
  1354. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_W,R_DS)));
  1355. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_W,R_ES)));
  1356. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_W,R_FS)));
  1357. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_W,R_GS)));
  1358. end;
  1359. procedure generate_interrupt_stackframe_exit;
  1360. begin
  1361. { restore the registers of an interrupt procedure }
  1362. { this was all with entrycode instead of exitcode !!}
  1363. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_EAX)));
  1364. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_EBX)));
  1365. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_ECX)));
  1366. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_EDX)));
  1367. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_ESI)));
  1368. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_L,R_EDI)));
  1369. { .... also the segment registers }
  1370. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_W,R_DS)));
  1371. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_W,R_ES)));
  1372. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_W,R_FS)));
  1373. procinfo^.aktexitcode^.concat(new(paicpu,op_reg(A_POP,S_W,R_GS)));
  1374. { this restores the flags }
  1375. procinfo^.aktexitcode^.concat(new(paicpu,op_none(A_IRET,S_NO)));
  1376. end;
  1377. { generates the code for threadvar initialisation }
  1378. procedure initialize_threadvar(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  1379. var
  1380. hr : treference;
  1381. begin
  1382. if (psym(p)^.typ=varsym) and
  1383. (vo_is_thread_var in pvarsym(p)^.varoptions) then
  1384. begin
  1385. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,pvarsym(p)^.getsize)));
  1386. reset_reference(hr);
  1387. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  1388. emitpushreferenceaddr(hr);
  1389. emitcall('FPC_INIT_THREADVAR');
  1390. end;
  1391. end;
  1392. { initilizes data of type t }
  1393. { if is_already_ref is true then the routines assumes }
  1394. { that r points to the data to initialize }
  1395. procedure initialize(t : pdef;const ref : treference;is_already_ref : boolean);
  1396. var
  1397. hr : treference;
  1398. begin
  1399. if is_ansistring(t) or
  1400. is_widestring(t) then
  1401. begin
  1402. emit_const_ref(A_MOV,S_L,0,
  1403. newreference(ref));
  1404. end
  1405. else
  1406. begin
  1407. reset_reference(hr);
  1408. hr.symbol:=t^.get_inittable_label;
  1409. emitpushreferenceaddr(hr);
  1410. if is_already_ref then
  1411. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,
  1412. newreference(ref))))
  1413. else
  1414. emitpushreferenceaddr(ref);
  1415. emitcall('FPC_INITIALIZE');
  1416. end;
  1417. end;
  1418. { finalizes data of type t }
  1419. { if is_already_ref is true then the routines assumes }
  1420. { that r points to the data to finalizes }
  1421. procedure finalize(t : pdef;const ref : treference;is_already_ref : boolean);
  1422. var
  1423. r : treference;
  1424. begin
  1425. if is_ansistring(t) or
  1426. is_widestring(t) then
  1427. begin
  1428. decrstringref(t,ref);
  1429. end
  1430. else
  1431. begin
  1432. reset_reference(r);
  1433. r.symbol:=t^.get_inittable_label;
  1434. emitpushreferenceaddr(r);
  1435. if is_already_ref then
  1436. exprasmlist^.concat(new(paicpu,op_ref(A_PUSH,S_L,
  1437. newreference(ref))))
  1438. else
  1439. emitpushreferenceaddr(ref);
  1440. emitcall('FPC_FINALIZE');
  1441. end;
  1442. end;
  1443. { generates the code for initialisation of local data }
  1444. procedure initialize_data(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  1445. var
  1446. hr : treference;
  1447. begin
  1448. if (psym(p)^.typ=varsym) and
  1449. assigned(pvarsym(p)^.vartype.def) and
  1450. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  1451. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  1452. pvarsym(p)^.vartype.def^.needs_inittable then
  1453. begin
  1454. if assigned(procinfo) then
  1455. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  1456. reset_reference(hr);
  1457. if psym(p)^.owner^.symtabletype in [localsymtable,inlinelocalsymtable] then
  1458. begin
  1459. hr.base:=procinfo^.framepointer;
  1460. hr.offset:=-pvarsym(p)^.address+pvarsym(p)^.owner^.address_fixup;
  1461. end
  1462. else
  1463. begin
  1464. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  1465. end;
  1466. initialize(pvarsym(p)^.vartype.def,hr,false);
  1467. end;
  1468. end;
  1469. { generates the code for incrementing the reference count of parameters }
  1470. procedure incr_data(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  1471. var
  1472. hr : treference;
  1473. begin
  1474. if (psym(p)^.typ=varsym) and
  1475. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  1476. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  1477. pvarsym(p)^.vartype.def^.needs_inittable and
  1478. (not assigned(pvarsym(p)^.localvarsym)) and
  1479. ((pvarsym(p)^.varspez=vs_value) {or
  1480. (pvarsym(p)^.varspez=vs_const) and
  1481. not(dont_copy_const_param(pvarsym(p)^.definition))}) then
  1482. begin
  1483. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  1484. reset_reference(hr);
  1485. hr.symbol:=pvarsym(p)^.vartype.def^.get_inittable_label;
  1486. emitpushreferenceaddr(hr);
  1487. reset_reference(hr);
  1488. hr.base:=procinfo^.framepointer;
  1489. hr.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  1490. emitpushreferenceaddr(hr);
  1491. reset_reference(hr);
  1492. emitcall('FPC_ADDREF');
  1493. end;
  1494. end;
  1495. { generates the code for finalisation of local data }
  1496. procedure finalize_data(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  1497. var
  1498. hr : treference;
  1499. begin
  1500. if (psym(p)^.typ=varsym) and
  1501. assigned(pvarsym(p)^.vartype.def) and
  1502. not((pvarsym(p)^.vartype.def^.deftype=objectdef) and
  1503. pobjectdef(pvarsym(p)^.vartype.def)^.is_class) and
  1504. (not assigned(pvarsym(p)^.localvarsym)) and
  1505. pvarsym(p)^.vartype.def^.needs_inittable then
  1506. begin
  1507. { not all kind of parameters need to be finalized }
  1508. if (psym(p)^.owner^.symtabletype=parasymtable) and
  1509. (pvarsym(p)^.varspez in [vs_out,vs_var,vs_const]) then
  1510. exit;
  1511. if assigned(procinfo) then
  1512. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  1513. reset_reference(hr);
  1514. case psym(p)^.owner^.symtabletype of
  1515. localsymtable,inlinelocalsymtable:
  1516. begin
  1517. hr.base:=procinfo^.framepointer;
  1518. hr.offset:=-pvarsym(p)^.address+pvarsym(p)^.owner^.address_fixup;
  1519. end;
  1520. parasymtable,inlineparasymtable:
  1521. begin
  1522. hr.base:=procinfo^.framepointer;
  1523. hr.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  1524. end;
  1525. else
  1526. hr.symbol:=newasmsymbol(pvarsym(p)^.mangledname);
  1527. end;
  1528. finalize(pvarsym(p)^.vartype.def,hr,false);
  1529. end;
  1530. end;
  1531. { generates the code to make local copies of the value parameters }
  1532. procedure copyvalueparas(p : pnamedindexobject);{$ifndef fpc}far;{$endif}
  1533. var
  1534. href1,href2 : treference;
  1535. r : preference;
  1536. power,len : longint;
  1537. opsize : topsize;
  1538. again,ok : pasmlabel;
  1539. begin
  1540. if (psym(p)^.typ=varsym) and
  1541. (pvarsym(p)^.varspez=vs_value) and
  1542. (push_addr_param(pvarsym(p)^.vartype.def)) then
  1543. begin
  1544. if is_open_array(pvarsym(p)^.vartype.def) or
  1545. is_array_of_const(pvarsym(p)^.vartype.def) then
  1546. begin
  1547. { get stack space }
  1548. new(r);
  1549. reset_reference(r^);
  1550. r^.base:=procinfo^.framepointer;
  1551. r^.offset:=pvarsym(p)^.address+4+procinfo^.para_offset;
  1552. getexplicitregister32(R_EDI);
  1553. exprasmlist^.concat(new(paicpu,
  1554. op_ref_reg(A_MOV,S_L,r,R_EDI)));
  1555. exprasmlist^.concat(new(paicpu,
  1556. op_reg(A_INC,S_L,R_EDI)));
  1557. if (parraydef(pvarsym(p)^.vartype.def)^.elesize<>1) then
  1558. begin
  1559. if ispowerof2(parraydef(pvarsym(p)^.vartype.def)^.elesize, power) then
  1560. exprasmlist^.concat(new(paicpu,
  1561. op_const_reg(A_SHL,S_L,
  1562. power,R_EDI)))
  1563. else
  1564. exprasmlist^.concat(new(paicpu,
  1565. op_const_reg(A_IMUL,S_L,
  1566. parraydef(pvarsym(p)^.vartype.def)^.elesize,R_EDI)));
  1567. end;
  1568. {$ifndef NOTARGETWIN32}
  1569. { windows guards only a few pages for stack growing, }
  1570. { so we have to access every page first }
  1571. if target_os.id=os_i386_win32 then
  1572. begin
  1573. getlabel(again);
  1574. getlabel(ok);
  1575. emitlab(again);
  1576. exprasmlist^.concat(new(paicpu,
  1577. op_const_reg(A_CMP,S_L,winstackpagesize,R_EDI)));
  1578. emitjmp(C_C,ok);
  1579. exprasmlist^.concat(new(paicpu,
  1580. op_const_reg(A_SUB,S_L,winstackpagesize-4,R_ESP)));
  1581. exprasmlist^.concat(new(paicpu,
  1582. op_reg(A_PUSH,S_L,R_EAX)));
  1583. exprasmlist^.concat(new(paicpu,
  1584. op_const_reg(A_SUB,S_L,winstackpagesize,R_EDI)));
  1585. emitjmp(C_None,again);
  1586. emitlab(ok);
  1587. exprasmlist^.concat(new(paicpu,
  1588. op_reg_reg(A_SUB,S_L,R_EDI,R_ESP)));
  1589. ungetregister32(R_EDI);
  1590. { now reload EDI }
  1591. new(r);
  1592. reset_reference(r^);
  1593. r^.base:=procinfo^.framepointer;
  1594. r^.offset:=pvarsym(p)^.address+4+procinfo^.para_offset;
  1595. getexplicitregister32(R_EDI);
  1596. exprasmlist^.concat(new(paicpu,
  1597. op_ref_reg(A_MOV,S_L,r,R_EDI)));
  1598. exprasmlist^.concat(new(paicpu,
  1599. op_reg(A_INC,S_L,R_EDI)));
  1600. if (parraydef(pvarsym(p)^.vartype.def)^.elesize<>1) then
  1601. begin
  1602. if ispowerof2(parraydef(pvarsym(p)^.vartype.def)^.elesize, power) then
  1603. exprasmlist^.concat(new(paicpu,
  1604. op_const_reg(A_SHL,S_L,
  1605. power,R_EDI)))
  1606. else
  1607. exprasmlist^.concat(new(paicpu,
  1608. op_const_reg(A_IMUL,S_L,
  1609. parraydef(pvarsym(p)^.vartype.def)^.elesize,R_EDI)));
  1610. end;
  1611. end
  1612. else
  1613. {$endif NOTARGETWIN32}
  1614. exprasmlist^.concat(new(paicpu,
  1615. op_reg_reg(A_SUB,S_L,R_EDI,R_ESP)));
  1616. { load destination }
  1617. exprasmlist^.concat(new(paicpu,
  1618. op_reg_reg(A_MOV,S_L,R_ESP,R_EDI)));
  1619. { don't destroy the registers! }
  1620. exprasmlist^.concat(new(paicpu,
  1621. op_reg(A_PUSH,S_L,R_ECX)));
  1622. exprasmlist^.concat(new(paicpu,
  1623. op_reg(A_PUSH,S_L,R_ESI)));
  1624. { load count }
  1625. new(r);
  1626. reset_reference(r^);
  1627. r^.base:=procinfo^.framepointer;
  1628. r^.offset:=pvarsym(p)^.address+4+procinfo^.para_offset;
  1629. exprasmlist^.concat(new(paicpu,
  1630. op_ref_reg(A_MOV,S_L,r,R_ECX)));
  1631. { load source }
  1632. new(r);
  1633. reset_reference(r^);
  1634. r^.base:=procinfo^.framepointer;
  1635. r^.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  1636. exprasmlist^.concat(new(paicpu,
  1637. op_ref_reg(A_MOV,S_L,r,R_ESI)));
  1638. { scheduled .... }
  1639. exprasmlist^.concat(new(paicpu,
  1640. op_reg(A_INC,S_L,R_ECX)));
  1641. { calculate size }
  1642. len:=parraydef(pvarsym(p)^.vartype.def)^.elesize;
  1643. opsize:=S_B;
  1644. if (len and 3)=0 then
  1645. begin
  1646. opsize:=S_L;
  1647. len:=len shr 2;
  1648. end
  1649. else
  1650. if (len and 1)=0 then
  1651. begin
  1652. opsize:=S_W;
  1653. len:=len shr 1;
  1654. end;
  1655. if ispowerof2(len, power) then
  1656. exprasmlist^.concat(new(paicpu,
  1657. op_const_reg(A_SHL,S_L,
  1658. power,R_ECX)))
  1659. else
  1660. exprasmlist^.concat(new(paicpu,
  1661. op_const_reg(A_IMUL,S_L,len,R_ECX)));
  1662. exprasmlist^.concat(new(paicpu,
  1663. op_none(A_REP,S_NO)));
  1664. case opsize of
  1665. S_B : exprasmlist^.concat(new(paicpu,op_none(A_MOVSB,S_NO)));
  1666. S_W : exprasmlist^.concat(new(paicpu,op_none(A_MOVSW,S_NO)));
  1667. S_L : exprasmlist^.concat(new(paicpu,op_none(A_MOVSD,S_NO)));
  1668. end;
  1669. ungetregister32(R_EDI);
  1670. exprasmlist^.concat(new(paicpu,
  1671. op_reg(A_POP,S_L,R_ESI)));
  1672. exprasmlist^.concat(new(paicpu,
  1673. op_reg(A_POP,S_L,R_ECX)));
  1674. { patch the new address }
  1675. new(r);
  1676. reset_reference(r^);
  1677. r^.base:=procinfo^.framepointer;
  1678. r^.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  1679. exprasmlist^.concat(new(paicpu,
  1680. op_reg_ref(A_MOV,S_L,R_ESP,r)));
  1681. end
  1682. else
  1683. if is_shortstring(pvarsym(p)^.vartype.def) then
  1684. begin
  1685. reset_reference(href1);
  1686. href1.base:=procinfo^.framepointer;
  1687. href1.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  1688. reset_reference(href2);
  1689. href2.base:=procinfo^.framepointer;
  1690. href2.offset:=-pvarsym(p)^.localvarsym^.address+pvarsym(p)^.localvarsym^.owner^.address_fixup;
  1691. copyshortstring(href2,href1,pstringdef(pvarsym(p)^.vartype.def)^.len,true,false);
  1692. end
  1693. else
  1694. begin
  1695. reset_reference(href1);
  1696. href1.base:=procinfo^.framepointer;
  1697. href1.offset:=pvarsym(p)^.address+procinfo^.para_offset;
  1698. reset_reference(href2);
  1699. href2.base:=procinfo^.framepointer;
  1700. href2.offset:=-pvarsym(p)^.localvarsym^.address+pvarsym(p)^.localvarsym^.owner^.address_fixup;
  1701. concatcopy(href1,href2,pvarsym(p)^.vartype.def^.size,true,true);
  1702. end;
  1703. end;
  1704. end;
  1705. procedure inittempansistrings;
  1706. var
  1707. hp : ptemprecord;
  1708. r : preference;
  1709. begin
  1710. hp:=templist;
  1711. while assigned(hp) do
  1712. begin
  1713. if hp^.temptype in [tt_ansistring,tt_freeansistring] then
  1714. begin
  1715. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  1716. new(r);
  1717. reset_reference(r^);
  1718. r^.base:=procinfo^.framepointer;
  1719. r^.offset:=hp^.pos;
  1720. emit_const_ref(A_MOV,S_L,0,r);
  1721. end;
  1722. hp:=hp^.next;
  1723. end;
  1724. end;
  1725. procedure finalizetempansistrings;
  1726. var
  1727. hp : ptemprecord;
  1728. hr : treference;
  1729. begin
  1730. hp:=templist;
  1731. while assigned(hp) do
  1732. begin
  1733. if hp^.temptype in [tt_ansistring,tt_freeansistring] then
  1734. begin
  1735. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  1736. reset_reference(hr);
  1737. hr.base:=procinfo^.framepointer;
  1738. hr.offset:=hp^.pos;
  1739. emitpushreferenceaddr(hr);
  1740. emitcall('FPC_ANSISTR_DECR_REF');
  1741. end;
  1742. hp:=hp^.next;
  1743. end;
  1744. end;
  1745. var
  1746. ls : longint;
  1747. procedure largest_size(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  1748. begin
  1749. if (psym(p)^.typ=varsym) and
  1750. (pvarsym(p)^.getvaluesize>ls) then
  1751. ls:=pvarsym(p)^.getvaluesize;
  1752. end;
  1753. procedure alignstack(alist : paasmoutput);
  1754. begin
  1755. {$ifdef dummy}
  1756. if (cs_optimize in aktglobalswitches) and
  1757. (aktoptprocessor in [classp5,classp6]) then
  1758. begin
  1759. ls:=0;
  1760. aktprocsym^.definition^.localst^.foreach({$ifndef TP}@{$endif}largest_size);
  1761. if ls>=8 then
  1762. alist^.insert(new(paicpu,op_const_reg(A_AND,S_L,-8,R_ESP)));
  1763. end;
  1764. {$endif dummy}
  1765. end;
  1766. procedure genentrycode(alist : paasmoutput;const proc_names:Tstringcontainer;make_global:boolean;
  1767. stackframe:longint;
  1768. var parasize:longint;var nostackframe:boolean;
  1769. inlined : boolean);
  1770. {
  1771. Generates the entry code for a procedure
  1772. }
  1773. var
  1774. hs : string;
  1775. {$ifdef GDB}
  1776. stab_function_name : Pai_stab_function_name;
  1777. {$endif GDB}
  1778. hr : preference;
  1779. p : psymtable;
  1780. r : treference;
  1781. oldlist,
  1782. oldexprasmlist : paasmoutput;
  1783. again : pasmlabel;
  1784. i : longint;
  1785. begin
  1786. oldexprasmlist:=exprasmlist;
  1787. exprasmlist:=alist;
  1788. if (not inlined) and (aktprocsym^.definition^.proctypeoption=potype_proginit) then
  1789. begin
  1790. emitinsertcall('FPC_INITIALIZEUNITS');
  1791. if target_info.target=target_I386_WIN32 then
  1792. begin
  1793. new(hr);
  1794. reset_reference(hr^);
  1795. hr^.symbol:=newasmsymbol(
  1796. 'U_SYSWIN32_ISCONSOLE');
  1797. if apptype=at_cui then
  1798. exprasmlist^.insert(new(paicpu,op_const_ref(A_MOV,S_B,
  1799. 1,hr)))
  1800. else
  1801. exprasmlist^.insert(new(paicpu,op_const_ref(A_MOV,S_B,
  1802. 0,hr)));
  1803. end;
  1804. oldlist:=exprasmlist;
  1805. exprasmlist:=new(paasmoutput,init);
  1806. p:=symtablestack;
  1807. while assigned(p) do
  1808. begin
  1809. p^.foreach({$ifndef TP}@{$endif}initialize_threadvar);
  1810. p:=p^.next;
  1811. end;
  1812. oldlist^.insertlist(exprasmlist);
  1813. dispose(exprasmlist,done);
  1814. exprasmlist:=oldlist;
  1815. end;
  1816. {$ifdef GDB}
  1817. if (not inlined) and (cs_debuginfo in aktmoduleswitches) then
  1818. exprasmlist^.insert(new(pai_force_line,init));
  1819. {$endif GDB}
  1820. { a constructor needs a help procedure }
  1821. if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
  1822. begin
  1823. if procinfo^._class^.is_class then
  1824. begin
  1825. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  1826. exprasmlist^.insert(new(paicpu,op_cond_sym(A_Jcc,C_Z,S_NO,faillabel)));
  1827. emitinsertcall('FPC_NEW_CLASS');
  1828. end
  1829. else
  1830. begin
  1831. exprasmlist^.insert(new(paicpu,op_cond_sym(A_Jcc,C_Z,S_NO,faillabel)));
  1832. emitinsertcall('FPC_HELP_CONSTRUCTOR');
  1833. getexplicitregister32(R_EDI);
  1834. exprasmlist^.insert(new(paicpu,op_const_reg(A_MOV,S_L,procinfo^._class^.vmt_offset,R_EDI)));
  1835. end;
  1836. end;
  1837. { don't load ESI, does the caller }
  1838. { we must do it for local function }
  1839. { that can be called from a foreach }
  1840. { of another object than self !! PM }
  1841. if assigned(procinfo^._class) and
  1842. (lexlevel>normal_function_level) then
  1843. maybe_loadesi;
  1844. { When message method contains self as a parameter,
  1845. we must load it into ESI }
  1846. If (po_containsself in aktprocsym^.definition^.procoptions) then
  1847. begin
  1848. new(hr);
  1849. reset_reference(hr^);
  1850. hr^.offset:=procinfo^.selfpointer_offset;
  1851. hr^.base:=procinfo^.framepointer;
  1852. exprasmlist^.insert(new(paicpu,op_ref_reg(A_MOV,S_L,hr,R_ESI)));
  1853. exprasmlist^.insert(new(pairegalloc,alloc(R_ESI)));
  1854. end;
  1855. { should we save edi,esi,ebx like C ? }
  1856. if (po_savestdregs in aktprocsym^.definition^.procoptions) then
  1857. begin
  1858. if (aktprocsym^.definition^.usedregisters and ($80 shr byte(R_EBX)))<>0 then
  1859. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EBX)));
  1860. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_ESI)));
  1861. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EDI)));
  1862. end;
  1863. { for the save all registers we can simply use a pusha,popa which
  1864. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1865. if (po_saveregisters in aktprocsym^.definition^.procoptions) then
  1866. begin
  1867. exprasmlist^.insert(new(paicpu,op_none(A_PUSHA,S_L)));
  1868. end;
  1869. { omit stack frame ? }
  1870. if not inlined then
  1871. if procinfo^.framepointer=stack_pointer then
  1872. begin
  1873. CGMessage(cg_d_stackframe_omited);
  1874. nostackframe:=true;
  1875. if (aktprocsym^.definition^.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  1876. parasize:=0
  1877. else
  1878. parasize:=aktprocsym^.definition^.parast^.datasize+procinfo^.para_offset-4;
  1879. if stackframe<>0 then
  1880. exprasmlist^.insert(new(paicpu,
  1881. op_const_reg(A_SUB,S_L,stackframe,R_ESP)));
  1882. end
  1883. else
  1884. begin
  1885. alignstack(alist);
  1886. if (aktprocsym^.definition^.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  1887. parasize:=0
  1888. else
  1889. parasize:=aktprocsym^.definition^.parast^.datasize+procinfo^.para_offset-8;
  1890. nostackframe:=false;
  1891. if stackframe<>0 then
  1892. begin
  1893. {$ifdef unused}
  1894. if (cs_littlesize in aktglobalswitches) and (stackframe<=65535) then
  1895. begin
  1896. if (cs_check_stack in aktlocalswitches) and
  1897. not(target_info.target in [target_386_freebsd,
  1898. target_i386_linux,target_i386_win32]) then
  1899. begin
  1900. emitinsertcall('FPC_STACKCHECK');
  1901. exprasmlist^.insert(new(paicpu,op_const(A_PUSH,S_L,stackframe)));
  1902. end;
  1903. if cs_profile in aktmoduleswitches then
  1904. genprofilecode;
  1905. { %edi is already saved when pocdecl is used
  1906. if ((target_info.target=target_linux) or (target_info.target=target_freebsd)) and
  1907. ((aktprocsym^.definition^.options and poexports)<>0) then
  1908. exprasmlist^.insert(new(Paicpu,op_reg(A_PUSH,S_L,R_EDI))); }
  1909. { ATTENTION:
  1910. never use ENTER in linux !!! (or freebsd MvdV)
  1911. the stack page fault does not support it PM }
  1912. exprasmlist^.insert(new(paicpu,op_const_const(A_ENTER,S_NO,stackframe,0)))
  1913. end
  1914. else
  1915. {$endif unused}
  1916. begin
  1917. { windows guards only a few pages for stack growing, }
  1918. { so we have to access every page first }
  1919. if (target_os.id=os_i386_win32) and
  1920. (stackframe>=winstackpagesize) then
  1921. begin
  1922. if stackframe div winstackpagesize<=5 then
  1923. begin
  1924. exprasmlist^.insert(new(paicpu,op_const_reg(A_SUB,S_L,stackframe-4,R_ESP)));
  1925. for i:=1 to stackframe div winstackpagesize do
  1926. begin
  1927. hr:=new_reference(R_ESP,stackframe-i*winstackpagesize);
  1928. exprasmlist^.concat(new(paicpu,
  1929. op_const_ref(A_MOV,S_L,0,hr)));
  1930. end;
  1931. exprasmlist^.concat(new(paicpu,
  1932. op_reg(A_PUSH,S_L,R_EAX)));
  1933. end
  1934. else
  1935. begin
  1936. getlabel(again);
  1937. getexplicitregister32(R_EDI);
  1938. exprasmlist^.concat(new(paicpu,
  1939. op_const_reg(A_MOV,S_L,stackframe div winstackpagesize,R_EDI)));
  1940. emitlab(again);
  1941. exprasmlist^.concat(new(paicpu,
  1942. op_const_reg(A_SUB,S_L,winstackpagesize-4,R_ESP)));
  1943. exprasmlist^.concat(new(paicpu,
  1944. op_reg(A_PUSH,S_L,R_EAX)));
  1945. exprasmlist^.concat(new(paicpu,
  1946. op_reg(A_DEC,S_L,R_EDI)));
  1947. emitjmp(C_NZ,again);
  1948. ungetregister32(R_EDI);
  1949. exprasmlist^.concat(new(paicpu,
  1950. op_const_reg(A_SUB,S_L,stackframe mod winstackpagesize,R_ESP)));
  1951. end
  1952. end
  1953. else
  1954. exprasmlist^.insert(new(paicpu,op_const_reg(A_SUB,S_L,stackframe,R_ESP)));
  1955. if (cs_check_stack in aktlocalswitches) and
  1956. not(target_info.target in [target_i386_freebsd,
  1957. target_i386_linux,target_i386_win32]) then
  1958. begin
  1959. emitinsertcall('FPC_STACKCHECK');
  1960. exprasmlist^.insert(new(paicpu,op_const(A_PUSH,S_L,stackframe)));
  1961. end;
  1962. if cs_profile in aktmoduleswitches then
  1963. genprofilecode;
  1964. exprasmlist^.insert(new(paicpu,op_reg_reg(A_MOV,S_L,R_ESP,R_EBP)));
  1965. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EBP)));
  1966. end;
  1967. end { endif stackframe <> 0 }
  1968. else
  1969. begin
  1970. if cs_profile in aktmoduleswitches then
  1971. genprofilecode;
  1972. exprasmlist^.insert(new(paicpu,op_reg_reg(A_MOV,S_L,R_ESP,R_EBP)));
  1973. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_EBP)));
  1974. end;
  1975. end;
  1976. if (po_interrupt in aktprocsym^.definition^.procoptions) then
  1977. generate_interrupt_stackframe_entry;
  1978. { initialize return value }
  1979. if (procinfo^.returntype.def<>pdef(voiddef)) and
  1980. (procinfo^.returntype.def^.needs_inittable) and
  1981. ((procinfo^.returntype.def^.deftype<>objectdef) or
  1982. not(pobjectdef(procinfo^.returntype.def)^.is_class)) then
  1983. begin
  1984. procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
  1985. reset_reference(r);
  1986. r.offset:=procinfo^.return_offset;
  1987. r.base:=procinfo^.framepointer;
  1988. initialize(procinfo^.returntype.def,r,ret_in_param(procinfo^.returntype.def));
  1989. end;
  1990. { initialisize local data like ansistrings }
  1991. case aktprocsym^.definition^.proctypeoption of
  1992. potype_unitinit:
  1993. begin
  1994. { using current_module^.globalsymtable is hopefully }
  1995. { more robust than symtablestack and symtablestack^.next }
  1996. psymtable(current_module^.globalsymtable)^.foreach({$ifndef TP}@{$endif}initialize_data);
  1997. psymtable(current_module^.localsymtable)^.foreach({$ifndef TP}@{$endif}initialize_data);
  1998. end;
  1999. { units have seperate code for initilization and finalization }
  2000. potype_unitfinalize: ;
  2001. else
  2002. aktprocsym^.definition^.localst^.foreach({$ifndef TP}@{$endif}initialize_data);
  2003. end;
  2004. { generate copies of call by value parameters }
  2005. if not(po_assembler in aktprocsym^.definition^.procoptions) and
  2006. (([pocall_cdecl,pocall_cppdecl]*aktprocsym^.definition^.proccalloptions)=[]) then
  2007. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}copyvalueparas);
  2008. { add a reference to all call by value/const parameters }
  2009. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}incr_data);
  2010. { initialisizes temp. ansi/wide string data }
  2011. inittempansistrings;
  2012. { do we need an exception frame because of ansi/widestrings ? }
  2013. if not inlined and
  2014. ((procinfo^.flags and pi_needs_implicit_finally)<>0) and
  2015. { but it's useless in init/final code of units }
  2016. not(aktprocsym^.definition^.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  2017. begin
  2018. usedinproc:=usedinproc or ($80 shr byte(R_EAX));
  2019. { Type of stack-frame must be pushed}
  2020. exprasmlist^.concat(new(paicpu,op_const(A_PUSH,S_L,1)));
  2021. emitcall('FPC_PUSHEXCEPTADDR');
  2022. exprasmlist^.concat(new(paicpu,
  2023. op_reg(A_PUSH,S_L,R_EAX)));
  2024. emitcall('FPC_SETJMP');
  2025. exprasmlist^.concat(new(paicpu,
  2026. op_reg(A_PUSH,S_L,R_EAX)));
  2027. exprasmlist^.concat(new(paicpu,
  2028. op_reg_reg(A_TEST,S_L,R_EAX,R_EAX)));
  2029. emitjmp(C_NE,aktexitlabel);
  2030. { probably we've to reload self here }
  2031. maybe_loadesi;
  2032. end;
  2033. if not inlined then
  2034. begin
  2035. if (cs_profile in aktmoduleswitches) or
  2036. (aktprocsym^.definition^.owner^.symtabletype=globalsymtable) or
  2037. (assigned(procinfo^._class) and (procinfo^._class^.owner^.symtabletype=globalsymtable)) then
  2038. make_global:=true;
  2039. hs:=proc_names.get;
  2040. {$ifdef GDB}
  2041. if (cs_debuginfo in aktmoduleswitches) and target_os.use_function_relative_addresses then
  2042. stab_function_name := new(pai_stab_function_name,init(strpnew(hs)));
  2043. {$EndIf GDB}
  2044. while hs<>'' do
  2045. begin
  2046. if make_global then
  2047. exprasmlist^.insert(new(pai_symbol,initname_global(hs,0)))
  2048. else
  2049. exprasmlist^.insert(new(pai_symbol,initname(hs,0)));
  2050. {$ifdef GDB}
  2051. if (cs_debuginfo in aktmoduleswitches) and
  2052. target_os.use_function_relative_addresses then
  2053. exprasmlist^.insert(new(pai_stab_function_name,init(strpnew(hs))));
  2054. {$endif GDB}
  2055. hs:=proc_names.get;
  2056. end;
  2057. if make_global or ((procinfo^.flags and pi_is_global) <> 0) then
  2058. aktprocsym^.is_global := True;
  2059. {$ifdef GDB}
  2060. if (cs_debuginfo in aktmoduleswitches) then
  2061. begin
  2062. if target_os.use_function_relative_addresses then
  2063. exprasmlist^.insert(stab_function_name);
  2064. exprasmlist^.insert(new(pai_stabs,init(aktprocsym^.stabstring)));
  2065. aktprocsym^.isstabwritten:=true;
  2066. end;
  2067. {$endif GDB}
  2068. { Align, gprof uses 16 byte granularity }
  2069. if (cs_profile in aktmoduleswitches) then
  2070. exprasmlist^.insert(new(pai_align,init_op(16,$90)))
  2071. else
  2072. if not(cs_littlesize in aktglobalswitches) then
  2073. exprasmlist^.insert(new(pai_align,init(16)));
  2074. end;
  2075. if inlined then
  2076. load_regvars(exprasmlist,nil);
  2077. exprasmlist:=oldexprasmlist;
  2078. end;
  2079. procedure handle_return_value(inlined : boolean;var uses_eax,uses_edx : boolean);
  2080. var
  2081. hr : preference;
  2082. op : Tasmop;
  2083. s : Topsize;
  2084. begin
  2085. uses_eax:=false;
  2086. uses_edx:=false;
  2087. if procinfo^.returntype.def<>pdef(voiddef) then
  2088. begin
  2089. {if ((procinfo^.flags and pi_operator)<>0) and
  2090. assigned(opsym) then
  2091. procinfo^.funcret_is_valid:=
  2092. procinfo^.funcret_is_valid or (opsym^.refs>0);}
  2093. if (procinfo^.funcret_state<>vs_assigned) and not inlined { and
  2094. ((procinfo^.flags and pi_uses_asm)=0)} then
  2095. CGMessage(sym_w_function_result_not_set);
  2096. hr:=new_reference(procinfo^.framepointer,procinfo^.return_offset);
  2097. if (procinfo^.returntype.def^.deftype in [orddef,enumdef]) then
  2098. begin
  2099. uses_eax:=true;
  2100. case procinfo^.returntype.def^.size of
  2101. 8:
  2102. begin
  2103. emit_ref_reg(A_MOV,S_L,hr,R_EAX);
  2104. hr:=new_reference(procinfo^.framepointer,procinfo^.return_offset+4);
  2105. emit_ref_reg(A_MOV,S_L,hr,R_EDX);
  2106. uses_edx:=true;
  2107. end;
  2108. 4:
  2109. emit_ref_reg(A_MOV,S_L,hr,R_EAX);
  2110. 2:
  2111. emit_ref_reg(A_MOV,S_W,hr,R_AX);
  2112. 1:
  2113. emit_ref_reg(A_MOV,S_B,hr,R_AL);
  2114. end;
  2115. end
  2116. else
  2117. if ret_in_acc(procinfo^.returntype.def) then
  2118. begin
  2119. uses_eax:=true;
  2120. emit_ref_reg(A_MOV,S_L,hr,R_EAX);
  2121. end
  2122. else
  2123. if (procinfo^.returntype.def^.deftype=floatdef) then
  2124. begin
  2125. floatloadops(pfloatdef(procinfo^.returntype.def)^.typ,op,s);
  2126. exprasmlist^.concat(new(paicpu,op_ref(op,s,hr)))
  2127. end
  2128. else
  2129. dispose(hr);
  2130. end
  2131. end;
  2132. procedure genexitcode(alist : paasmoutput;parasize:longint;nostackframe,inlined:boolean);
  2133. var
  2134. {$ifdef GDB}
  2135. mangled_length : longint;
  2136. p : pchar;
  2137. st : string[2];
  2138. {$endif GDB}
  2139. nofinal,okexitlabel,noreraiselabel,nodestroycall : pasmlabel;
  2140. hr : treference;
  2141. uses_eax,uses_edx,uses_esi : boolean;
  2142. oldexprasmlist : paasmoutput;
  2143. ai : paicpu;
  2144. pd : pprocdef;
  2145. begin
  2146. oldexprasmlist:=exprasmlist;
  2147. exprasmlist:=alist;
  2148. if aktexitlabel^.is_used then
  2149. exprasmlist^.insert(new(pai_label,init(aktexitlabel)));
  2150. { call the destructor help procedure }
  2151. if (aktprocsym^.definition^.proctypeoption=potype_destructor) and
  2152. assigned(procinfo^._class) then
  2153. begin
  2154. if procinfo^._class^.is_class then
  2155. begin
  2156. emitinsertcall('FPC_DISPOSE_CLASS');
  2157. end
  2158. else
  2159. begin
  2160. emitinsertcall('FPC_HELP_DESTRUCTOR');
  2161. getexplicitregister32(R_EDI);
  2162. exprasmlist^.insert(new(paicpu,op_const_reg(A_MOV,S_L,procinfo^._class^.vmt_offset,R_EDI)));
  2163. { must the object be finalized ? }
  2164. if procinfo^._class^.needs_inittable then
  2165. begin
  2166. getlabel(nofinal);
  2167. exprasmlist^.insert(new(pai_label,init(nofinal)));
  2168. emitinsertcall('FPC_FINALIZE');
  2169. ungetregister32(R_EDI);
  2170. exprasmlist^.insert(new(paicpu,op_reg(A_PUSH,S_L,R_ESI)));
  2171. exprasmlist^.insert(new(paicpu,op_sym(A_PUSH,S_L,procinfo^._class^.get_inittable_label)));
  2172. ai:=new(paicpu,op_sym(A_Jcc,S_NO,nofinal));
  2173. ai^.SetCondition(C_Z);
  2174. exprasmlist^.insert(ai);
  2175. reset_reference(hr);
  2176. hr.base:=R_EBP;
  2177. hr.offset:=8;
  2178. exprasmlist^.insert(new(paicpu,op_const_ref(A_CMP,S_L,0,newreference(hr))));
  2179. end;
  2180. end;
  2181. end;
  2182. { finalize temporary data }
  2183. finalizetempansistrings;
  2184. { finalize local data like ansistrings}
  2185. case aktprocsym^.definition^.proctypeoption of
  2186. potype_unitfinalize:
  2187. begin
  2188. { using current_module^.globalsymtable is hopefully }
  2189. { more robust than symtablestack and symtablestack^.next }
  2190. psymtable(current_module^.globalsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  2191. psymtable(current_module^.localsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  2192. end;
  2193. { units have seperate code for initialization and finalization }
  2194. potype_unitinit: ;
  2195. else
  2196. aktprocsym^.definition^.localst^.foreach({$ifndef TP}@{$endif}finalize_data);
  2197. end;
  2198. { finalize paras data }
  2199. if assigned(aktprocsym^.definition^.parast) then
  2200. aktprocsym^.definition^.parast^.foreach({$ifndef TP}@{$endif}finalize_data);
  2201. { do we need to handle exceptions because of ansi/widestrings ? }
  2202. if not inlined and
  2203. ((procinfo^.flags and pi_needs_implicit_finally)<>0) and
  2204. { but it's useless in init/final code of units }
  2205. not(aktprocsym^.definition^.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  2206. begin
  2207. { the exception helper routines modify all registers }
  2208. aktprocsym^.definition^.usedregisters:=$ff;
  2209. getlabel(noreraiselabel);
  2210. emitcall('FPC_POPADDRSTACK');
  2211. exprasmlist^.concat(new(paicpu,
  2212. op_reg(A_POP,S_L,R_EAX)));
  2213. exprasmlist^.concat(new(paicpu,
  2214. op_reg_reg(A_TEST,S_L,R_EAX,R_EAX)));
  2215. emitjmp(C_E,noreraiselabel);
  2216. if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
  2217. begin
  2218. if assigned(procinfo^._class) then
  2219. begin
  2220. pd:=procinfo^._class^.searchdestructor;
  2221. if assigned(pd) then
  2222. begin
  2223. getlabel(nodestroycall);
  2224. emit_const_ref(A_CMP,S_L,0,new_reference(procinfo^.framepointer,
  2225. procinfo^.selfpointer_offset));
  2226. emitjmp(C_E,nodestroycall);
  2227. if procinfo^._class^.is_class then
  2228. begin
  2229. emit_const(A_PUSH,S_L,1);
  2230. emit_reg(A_PUSH,S_L,R_ESI);
  2231. end
  2232. else
  2233. begin
  2234. emit_reg(A_PUSH,S_L,R_ESI);
  2235. emit_sym(A_PUSH,S_L,newasmsymbol(procinfo^._class^.vmt_mangledname));
  2236. end;
  2237. if (po_virtualmethod in pd^.procoptions) then
  2238. begin
  2239. emit_ref_reg(A_MOV,S_L,new_reference(R_ESI,0),R_EDI);
  2240. emit_ref(A_CALL,S_NO,new_reference(R_EDI,procinfo^._class^.vmtmethodoffset(pd^.extnumber)));
  2241. end
  2242. else
  2243. emitcall(pd^.mangledname);
  2244. { not necessary because the result is never assigned in the
  2245. case of an exception (FK)
  2246. emit_const_reg(A_MOV,S_L,0,R_ESI);
  2247. emit_const_ref(A_MOV,S_L,0,new_reference(procinfo^.framepointer,8));
  2248. }
  2249. emitlab(nodestroycall);
  2250. end;
  2251. end
  2252. end
  2253. else
  2254. { must be the return value finalized before reraising the exception? }
  2255. if (procinfo^.returntype.def<>pdef(voiddef)) and
  2256. (procinfo^.returntype.def^.needs_inittable) and
  2257. ((procinfo^.returntype.def^.deftype<>objectdef) or
  2258. not(pobjectdef(procinfo^.returntype.def)^.is_class)) then
  2259. begin
  2260. reset_reference(hr);
  2261. hr.offset:=procinfo^.return_offset;
  2262. hr.base:=procinfo^.framepointer;
  2263. finalize(procinfo^.returntype.def,hr,ret_in_param(procinfo^.returntype.def));
  2264. end;
  2265. emitcall('FPC_RERAISE');
  2266. emitlab(noreraiselabel);
  2267. end;
  2268. { call __EXIT for main program }
  2269. if (not DLLsource) and (not inlined) and (aktprocsym^.definition^.proctypeoption=potype_proginit) then
  2270. begin
  2271. emitcall('FPC_DO_EXIT');
  2272. end;
  2273. { handle return value }
  2274. uses_eax:=false;
  2275. uses_edx:=false;
  2276. uses_esi:=false;
  2277. if not(po_assembler in aktprocsym^.definition^.procoptions) then
  2278. if (aktprocsym^.definition^.proctypeoption<>potype_constructor) then
  2279. handle_return_value(inlined,uses_eax,uses_edx)
  2280. else
  2281. begin
  2282. { successful constructor deletes the zero flag }
  2283. { and returns self in eax }
  2284. { eax must be set to zero if the allocation failed !!! }
  2285. getlabel(okexitlabel);
  2286. emitjmp(C_NONE,okexitlabel);
  2287. emitlab(faillabel);
  2288. if procinfo^._class^.is_class then
  2289. begin
  2290. emit_ref_reg(A_MOV,S_L,new_reference(procinfo^.framepointer,8),R_ESI);
  2291. emitcall('FPC_HELP_FAIL_CLASS');
  2292. end
  2293. else
  2294. begin
  2295. emit_ref_reg(A_MOV,S_L,new_reference(procinfo^.framepointer,12),R_ESI);
  2296. getexplicitregister32(R_EDI);
  2297. emit_const_reg(A_MOV,S_L,procinfo^._class^.vmt_offset,R_EDI);
  2298. emitcall('FPC_HELP_FAIL');
  2299. ungetregister32(R_EDI);
  2300. end;
  2301. emitlab(okexitlabel);
  2302. emit_reg_reg(A_MOV,S_L,R_ESI,R_EAX);
  2303. emit_reg_reg(A_TEST,S_L,R_ESI,R_ESI);
  2304. uses_eax:=true;
  2305. uses_esi:=true;
  2306. end;
  2307. { stabs uses the label also ! }
  2308. if aktexit2label^.is_used or
  2309. ((cs_debuginfo in aktmoduleswitches) and not inlined) then
  2310. emitlab(aktexit2label);
  2311. { gives problems for long mangled names }
  2312. {list^.concat(new(pai_symbol,init(aktprocsym^.definition^.mangledname+'_end')));}
  2313. { should we restore edi ? }
  2314. { for all i386 gcc implementations }
  2315. if (po_savestdregs in aktprocsym^.definition^.procoptions) then
  2316. begin
  2317. if (aktprocsym^.definition^.usedregisters and ($80 shr byte(R_EBX)))<>0 then
  2318. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_EBX)));
  2319. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_ESI)));
  2320. exprasmlist^.concat(new(paicpu,op_reg(A_POP,S_L,R_EDI)));
  2321. { here we could reset R_EBX
  2322. but that is risky because it only works
  2323. if genexitcode is called after genentrycode
  2324. so lets skip this for the moment PM
  2325. aktprocsym^.definition^.usedregisters:=
  2326. aktprocsym^.definition^.usedregisters or not ($80 shr byte(R_EBX));
  2327. }
  2328. end;
  2329. { for the save all registers we can simply use a pusha,popa which
  2330. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  2331. if (po_saveregisters in aktprocsym^.definition^.procoptions) then
  2332. begin
  2333. if uses_esi then
  2334. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_ESI,new_reference(R_ESP,4))));
  2335. if uses_edx then
  2336. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDX,new_reference(R_ESP,20))));
  2337. if uses_eax then
  2338. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EAX,new_reference(R_ESP,28))));
  2339. exprasmlist^.concat(new(paicpu,op_none(A_POPA,S_L)))
  2340. end;
  2341. if not(nostackframe) then
  2342. begin
  2343. if not inlined then
  2344. exprasmlist^.concat(new(paicpu,op_none(A_LEAVE,S_NO)));
  2345. end
  2346. else
  2347. begin
  2348. if (gettempsize<>0) and not inlined then
  2349. exprasmlist^.insert(new(paicpu,
  2350. op_const_reg(A_ADD,S_L,gettempsize,R_ESP)));
  2351. end;
  2352. { parameters are limited to 65535 bytes because }
  2353. { ret allows only imm16 }
  2354. if (parasize>65535) and not(pocall_clearstack in aktprocsym^.definition^.proccalloptions) then
  2355. CGMessage(cg_e_parasize_too_big);
  2356. { at last, the return is generated }
  2357. if not inlined then
  2358. if (po_interrupt in aktprocsym^.definition^.procoptions) then
  2359. begin
  2360. if uses_esi then
  2361. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_ESI,new_reference(R_ESP,16))));
  2362. if uses_edx then
  2363. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EDX,new_reference(R_ESP,12))));
  2364. if uses_eax then
  2365. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,S_L,R_EAX,new_reference(R_ESP,0))));
  2366. generate_interrupt_stackframe_exit;
  2367. end
  2368. else
  2369. begin
  2370. {Routines with the poclearstack flag set use only a ret.}
  2371. { also routines with parasize=0 }
  2372. if (pocall_clearstack in aktprocsym^.definition^.proccalloptions) then
  2373. begin
  2374. {$ifndef OLD_C_STACK}
  2375. { complex return values are removed from stack in C code PM }
  2376. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  2377. exprasmlist^.concat(new(paicpu,op_const(A_RET,S_NO,4)))
  2378. else
  2379. {$endif not OLD_C_STACK}
  2380. exprasmlist^.concat(new(paicpu,op_none(A_RET,S_NO)));
  2381. end
  2382. else if (parasize=0) then
  2383. exprasmlist^.concat(new(paicpu,op_none(A_RET,S_NO)))
  2384. else
  2385. exprasmlist^.concat(new(paicpu,op_const(A_RET,S_NO,parasize)));
  2386. end;
  2387. if not inlined then
  2388. exprasmlist^.concat(new(pai_symbol_end,initname(aktprocsym^.definition^.mangledname)));
  2389. {$ifdef GDB}
  2390. if (cs_debuginfo in aktmoduleswitches) and not inlined then
  2391. begin
  2392. aktprocsym^.concatstabto(exprasmlist);
  2393. if assigned(procinfo^._class) then
  2394. if (not assigned(procinfo^.parent) or
  2395. not assigned(procinfo^.parent^._class)) then
  2396. begin
  2397. if not procinfo^._class^.is_class then
  2398. st:='v'
  2399. else
  2400. st:='p';
  2401. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2402. '"$t:'+st+procinfo^._class^.numberstring+'",'+
  2403. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.selfpointer_offset)))))
  2404. end
  2405. else
  2406. begin
  2407. if not procinfo^._class^.is_class then
  2408. st:='*'
  2409. else
  2410. st:='';
  2411. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2412. '"$t:r'+st+procinfo^._class^.numberstring+'",'+
  2413. tostr(N_RSYM)+',0,0,'+tostr(GDB_i386index[R_ESI])))));
  2414. end;
  2415. { define calling EBP as pseudo local var PM }
  2416. { this enables test if the function is a local one !! }
  2417. if assigned(procinfo^.parent) and (lexlevel>normal_function_level) then
  2418. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2419. '"parent_ebp:'+voidpointerdef^.numberstring+'",'+
  2420. tostr(N_LSYM)+',0,0,'+tostr(procinfo^.framepointer_offset)))));
  2421. if (pdef(aktprocsym^.definition^.rettype.def) <> pdef(voiddef)) then
  2422. begin
  2423. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  2424. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2425. '"'+aktprocsym^.name+':X*'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  2426. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))))
  2427. else
  2428. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2429. '"'+aktprocsym^.name+':X'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  2430. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))));
  2431. if (m_result in aktmodeswitches) then
  2432. if ret_in_param(aktprocsym^.definition^.rettype.def) then
  2433. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2434. '"RESULT:X*'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  2435. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))))
  2436. else
  2437. exprasmlist^.concat(new(pai_stabs,init(strpnew(
  2438. '"RESULT:X'+aktprocsym^.definition^.rettype.def^.numberstring+'",'+
  2439. tostr(N_PSYM)+',0,0,'+tostr(procinfo^.return_offset)))));
  2440. end;
  2441. mangled_length:=length(aktprocsym^.definition^.mangledname);
  2442. getmem(p,2*mangled_length+50);
  2443. strpcopy(p,'192,0,0,');
  2444. strpcopy(strend(p),aktprocsym^.definition^.mangledname);
  2445. if (target_os.use_function_relative_addresses) then
  2446. begin
  2447. strpcopy(strend(p),'-');
  2448. strpcopy(strend(p),aktprocsym^.definition^.mangledname);
  2449. end;
  2450. exprasmlist^.concat(new(pai_stabn,init(strnew(p))));
  2451. {list^.concat(new(pai_stabn,init(strpnew('192,0,0,'
  2452. +aktprocsym^.definition^.mangledname))));
  2453. p[0]:='2';p[1]:='2';p[2]:='4';
  2454. strpcopy(strend(p),'_end');}
  2455. strpcopy(p,'224,0,0,'+aktexit2label^.name);
  2456. if (target_os.use_function_relative_addresses) then
  2457. begin
  2458. strpcopy(strend(p),'-');
  2459. strpcopy(strend(p),aktprocsym^.definition^.mangledname);
  2460. end;
  2461. exprasmlist^.concatlist(withdebuglist);
  2462. exprasmlist^.concat(new(pai_stabn,init(
  2463. strnew(p))));
  2464. { strpnew('224,0,0,'
  2465. +aktprocsym^.definition^.mangledname+'_end'))));}
  2466. freemem(p,2*mangled_length+50);
  2467. end;
  2468. {$endif GDB}
  2469. if inlined then
  2470. cleanup_regvars(exprasmlist);
  2471. exprasmlist:=oldexprasmlist;
  2472. end;
  2473. procedure genimplicitunitfinal(alist : paasmoutput);
  2474. begin
  2475. { using current_module^.globalsymtable is hopefully }
  2476. { more robust than symtablestack and symtablestack^.next }
  2477. psymtable(current_module^.globalsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  2478. psymtable(current_module^.localsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  2479. exprasmlist^.insert(new(pai_symbol,initname_global('FINALIZE$$'+current_module^.modulename^,0)));
  2480. exprasmlist^.insert(new(pai_symbol,initname_global(target_os.cprefix+current_module^.modulename^+'_finalize',0)));
  2481. {$ifdef GDB}
  2482. if (cs_debuginfo in aktmoduleswitches) and
  2483. target_os.use_function_relative_addresses then
  2484. exprasmlist^.insert(new(pai_stab_function_name,init(strpnew('FINALIZE$$'+current_module^.modulename^))));
  2485. {$endif GDB}
  2486. exprasmlist^.concat(new(paicpu,op_none(A_RET,S_NO)));
  2487. alist^.concatlist(exprasmlist);
  2488. end;
  2489. procedure genimplicitunitinit(alist : paasmoutput);
  2490. begin
  2491. { using current_module^.globalsymtable is hopefully }
  2492. { more robust than symtablestack and symtablestack^.next }
  2493. psymtable(current_module^.globalsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  2494. psymtable(current_module^.localsymtable)^.foreach({$ifndef TP}@{$endif}finalize_data);
  2495. exprasmlist^.insert(new(pai_symbol,initname_global('INIT$$'+current_module^.modulename^,0)));
  2496. exprasmlist^.insert(new(pai_symbol,initname_global(target_os.cprefix+current_module^.modulename^+'_init',0)));
  2497. {$ifdef GDB}
  2498. if (cs_debuginfo in aktmoduleswitches) and
  2499. target_os.use_function_relative_addresses then
  2500. exprasmlist^.insert(new(pai_stab_function_name,init(strpnew('INIT$$'+current_module^.modulename^))));
  2501. {$endif GDB}
  2502. exprasmlist^.concat(new(paicpu,op_none(A_RET,S_NO)));
  2503. alist^.concatlist(exprasmlist);
  2504. end;
  2505. {$ifdef test_dest_loc}
  2506. procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
  2507. begin
  2508. if (dest_loc.loc=LOC_CREGISTER) or (dest_loc.loc=LOC_REGISTER) then
  2509. begin
  2510. emit_reg_reg(A_MOV,s,reg,dest_loc.register);
  2511. set_location(p^.location,dest_loc);
  2512. in_dest_loc:=true;
  2513. end
  2514. else
  2515. if (dest_loc.loc=LOC_REFERENCE) or (dest_loc.loc=LOC_MEM) then
  2516. begin
  2517. exprasmlist^.concat(new(paicpu,op_reg_ref(A_MOV,s,reg,newreference(dest_loc.reference))));
  2518. set_location(p^.location,dest_loc);
  2519. in_dest_loc:=true;
  2520. end
  2521. else
  2522. internalerror(20080);
  2523. end;
  2524. {$endif test_dest_loc}
  2525. end.
  2526. {
  2527. $Log$
  2528. Revision 1.19 2000-10-14 10:14:46 peter
  2529. * moehrendorf oct 2000 rewrite
  2530. Revision 1.18 2000/10/10 14:55:28 jonas
  2531. * added missing regallocs for edi in emit_mov_ref_reg64 (merged)
  2532. Revision 1.17 2000/10/01 19:48:23 peter
  2533. * lot of compile updates for cg11
  2534. Revision 1.16 2000/09/30 16:08:45 peter
  2535. * more cg11 updates
  2536. Revision 1.15 2000/09/24 15:06:12 peter
  2537. * use defines.inc
  2538. Revision 1.14 2000/09/16 12:22:52 peter
  2539. * freebsd support merged
  2540. Revision 1.13 2000/08/27 16:11:49 peter
  2541. * moved some util functions from globals,cobjects to cutils
  2542. * splitted files into finput,fmodule
  2543. Revision 1.12 2000/08/24 19:07:54 peter
  2544. * don't initialize if localvarsym is set because that varsym will
  2545. already be initialized
  2546. * first initialize local data before copy of value para's (merged)
  2547. Revision 1.11 2000/08/19 20:09:33 peter
  2548. * check size after checking openarray in push_value_para (merged)
  2549. Revision 1.10 2000/08/16 13:06:06 florian
  2550. + support of 64 bit integer constants
  2551. Revision 1.9 2000/08/10 18:42:03 peter
  2552. * fixed for constants in emit_push_mem_size for go32v2 (merged)
  2553. Revision 1.8 2000/08/07 11:29:40 jonas
  2554. + emit_push_mem_size() which pushes a value in memory of a certain size
  2555. * pushsetelement() and pushvaluepara() use this new procedure, because
  2556. otherwise they could sometimes try to push data past the end of the
  2557. heap, causing a crash
  2558. (merged from fixes branch)
  2559. Revision 1.7 2000/08/03 13:17:25 jonas
  2560. + allow regvars to be used inside inlined procs, which required the
  2561. following changes:
  2562. + load regvars in genentrycode/free them in genexitcode (cgai386)
  2563. * moved all regvar related code to new regvars unit
  2564. + added pregvarinfo type to hcodegen
  2565. + added regvarinfo field to tprocinfo (symdef/symdefh)
  2566. * deallocate the regvars of the caller in secondprocinline before
  2567. inlining the called procedure and reallocate them afterwards
  2568. Revision 1.6 2000/08/02 08:05:04 jonas
  2569. * fixed web bug1087
  2570. * allocate R_ECX explicitely if it's used
  2571. (merged from fixes branch)
  2572. Revision 1.5 2000/07/27 09:25:05 jonas
  2573. * moved locflags2reg() procedure from cg386add to cgai386
  2574. + added locjump2reg() procedure to cgai386
  2575. * fixed internalerror(2002) when the result of a case expression has
  2576. LOC_JUMP
  2577. (all merged from fixes branch)
  2578. Revision 1.4 2000/07/21 15:14:02 jonas
  2579. + added is_addr field for labels, if they are only used for getting the address
  2580. (e.g. for io checks) and corresponding getaddrlabel() procedure
  2581. Revision 1.3 2000/07/13 12:08:25 michael
  2582. + patched to 1.1.0 with former 1.09patch from peter
  2583. Revision 1.2 2000/07/13 11:32:37 michael
  2584. + removed logs
  2585. }