cga.pas 105 KB

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