rgobj.pas 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the base class for the register allocator
  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. {$i fpcdefs.inc}
  19. {# @abstract(Abstract register allocator unit)
  20. This unit contains services to allocate, free
  21. references and registers which are used by
  22. the code generator.
  23. }
  24. unit rgobj;
  25. interface
  26. uses
  27. cpubase,
  28. cpuinfo,
  29. aasmbase,aasmtai,aasmcpu,
  30. cclasses,globtype,cginfo,cgbase,node
  31. {$ifdef delphi}
  32. ,dmisc
  33. {$endif}
  34. ;
  35. type
  36. regvar_longintarray = array[firstreg..lastreg] of longint;
  37. regvarint_longintarray = array[first_supreg..last_supreg] of longint;
  38. regvar_booleanarray = array[firstreg..lastreg] of boolean;
  39. regvar_ptreearray = array[firstreg..lastreg] of tnode;
  40. tpushedsavedloc = record
  41. case byte of
  42. 0: (pushed: boolean);
  43. 1: (ofs: longint);
  44. end;
  45. tpushedsaved = array[firstreg..lastreg] of tpushedsavedloc;
  46. Tpushedsavedint = array[first_supreg..last_supreg] of Tpushedsavedloc;
  47. {#
  48. This class implements the abstract register allocator
  49. It is used by the code generator to allocate and free
  50. registers which might be valid across nodes. It also
  51. contains utility routines related to registers.
  52. Some of the methods in this class should be overriden
  53. by cpu-specific implementations.
  54. }
  55. trgobj = class
  56. { The "usableregsxxx" contain all registers of type "xxx" that }
  57. { aren't currently allocated to a regvar. The "unusedregsxxx" }
  58. { contain all registers of type "xxx" that aren't currenly }
  59. { allocated }
  60. unusedregsint,usableregsint:Tsupregset;
  61. unusedregsfpu,usableregsfpu : tregisterset;
  62. unusedregsmm,usableregsmm : tregisterset;
  63. { these counters contain the number of elements in the }
  64. { unusedregsxxx/usableregsxxx sets }
  65. countunusedregsint,
  66. countunusedregsfpu,
  67. countunusedregsmm : byte;
  68. countusableregsint,
  69. countusableregsfpu,
  70. countusableregsmm : byte;
  71. { Contains the registers which are really used by the proc itself.
  72. It doesn't take care of registers used by called procedures
  73. }
  74. usedbyproc,
  75. usedinproc : tregisterset;
  76. usedintbyproc,usedintinproc:Tsupregset;
  77. reg_pushes : regvar_longintarray;
  78. reg_pushes_int : regvarint_longintarray;
  79. is_reg_var : regvar_booleanarray;
  80. is_reg_var_int:Tsupregset;
  81. regvar_loaded: regvar_booleanarray;
  82. regvar_loaded_int: Tsupregset;
  83. { tries to hold the amount of times which the current tree is processed }
  84. t_times: longint;
  85. constructor create;
  86. {# Allocate a general purpose register
  87. An internalerror will be generated if there
  88. is no more free registers which can be allocated
  89. }
  90. function getregisterint(list:Taasmoutput;size:Tcgsize):Tregister;virtual;
  91. {# Free a general purpose register
  92. @param(r register to free)
  93. }
  94. procedure ungetregisterint(list: taasmoutput; r : tregister); virtual;
  95. {# Allocate a floating point register
  96. An internalerror will be generated if there
  97. is no more free registers which can be allocated
  98. }
  99. function getregisterfpu(list: taasmoutput) : tregister; virtual;
  100. {# Free a floating point register
  101. @param(r register to free)
  102. }
  103. procedure ungetregisterfpu(list: taasmoutput; r : tregister); virtual;
  104. function getregistermm(list: taasmoutput) : tregister; virtual;
  105. procedure ungetregistermm(list: taasmoutput; r : tregister); virtual;
  106. {# Allocate an address register.
  107. Address registers are the only registers which can
  108. be used as a base register in references (treference).
  109. On most cpu's this is the same as a general purpose
  110. register.
  111. An internalerror will be generated if there
  112. is no more free registers which can be allocated
  113. }
  114. function getaddressregister(list:Taasmoutput):Tregister;virtual;
  115. procedure ungetaddressregister(list: taasmoutput; r: tregister); virtual;
  116. {# Verify if the specified register is an address or
  117. general purpose register. Returns TRUE if @var(reg)
  118. is an adress register.
  119. This routine should only be used to check on
  120. general purpose or address register. It will
  121. not work on multimedia or floating point
  122. registers
  123. @param(reg register to verify)
  124. }
  125. function isaddressregister(reg: tregister): boolean; virtual;
  126. {# Tries to allocate the passed register, if possible
  127. @param(r specific register to allocate)
  128. }
  129. function getexplicitregisterint(list:Taasmoutput;r:Tnewregister):Tregister;virtual;
  130. {# Tries to allocate the passed fpu register, if possible
  131. @param(r specific register to allocate)
  132. }
  133. function getexplicitregisterfpu(list : taasmoutput; r : Toldregister) : tregister;
  134. {# Deallocate any kind of register }
  135. procedure ungetregister(list: taasmoutput; r : tregister); virtual;
  136. {# Deallocate all registers which are allocated
  137. in the specified reference. On most systems,
  138. this will free the base and index registers
  139. of the specified reference.
  140. @param(ref reference which must have its registers freed)
  141. }
  142. procedure ungetreference(list: taasmoutput; const ref : treference); virtual;
  143. {# Reset the register allocator information (usable registers etc) }
  144. procedure cleartempgen;virtual;
  145. {# Convert a register to a specified register size, and return that register size }
  146. function makeregsize(reg: tregister; size: tcgsize): tregister; virtual;
  147. {# saves register variables (restoring happens automatically) }
  148. procedure saveintregvars(list:Taasmoutput;const s:Tsupregset);
  149. procedure saveotherregvars(list:Taasmoutput;const s:Tregisterset);
  150. {# Saves in temporary references (allocated via the temp. allocator)
  151. the registers defined in @var(s). The registers are only saved
  152. if they are currently in use, otherwise they are left as is.
  153. On processors which have instructions which manipulate the stack,
  154. this routine should be overriden for performance reasons.
  155. @param(list) List to add the instruction to
  156. @param(saved) Array of saved register information
  157. @param(s) Registers which might require saving
  158. }
  159. procedure saveusedintregisters(list:Taasmoutput;
  160. var saved:Tpushedsavedint;
  161. const s:Tsupregset);virtual;
  162. procedure saveusedotherregisters(list:Taasmoutput;
  163. var saved:Tpushedsaved;
  164. const s:Tregisterset);virtual;
  165. {# Restores the registers which were saved with a call
  166. to @var(saveusedregisters).
  167. On processors which have instructions which manipulate the stack,
  168. this routine should be overriden for performance reasons.
  169. }
  170. procedure restoreusedintregisters(list:Taasmoutput;
  171. const saved:Tpushedsavedint);virtual;
  172. procedure restoreusedotherregisters(list:Taasmoutput;
  173. const saved:Tpushedsaved);virtual;
  174. { used when deciding which registers to use for regvars }
  175. procedure incrementintregisterpushed(const s:Tsupregset);
  176. procedure incrementotherregisterpushed(const s: tregisterset);
  177. procedure clearregistercount;
  178. procedure resetusableregisters;virtual;
  179. procedure makeregvarint(reg:Tnewregister);
  180. procedure makeregvarother(reg:Tregister);
  181. procedure saveStateForInline(var state: pointer);virtual;
  182. procedure restoreStateAfterInline(var state: pointer);virtual;
  183. procedure saveUnusedState(var state: pointer);virtual;
  184. procedure restoreUnusedState(var state: pointer);virtual;
  185. protected
  186. { the following two contain the common (generic) code for all }
  187. { get- and ungetregisterxxx functions/procedures }
  188. function getregistergen(list: taasmoutput; const lowreg, highreg: Toldregister;
  189. var unusedregs:Tregisterset; var countunusedregs: byte): tregister;
  190. function getregistergenint(list:Taasmoutput;subreg:Tsubregister;
  191. const lowreg,highreg:Tsuperregister;
  192. var fusedinproc,fusedbyproc,unusedregs:Tsupregset;
  193. var countunusedregs:byte):Tregister;
  194. procedure ungetregistergen(list: taasmoutput; const r: tregister;
  195. const usableregs: tregisterset; var unusedregs: tregisterset; var countunusedregs: byte);
  196. procedure ungetregistergenint(list:taasmoutput;const r:Tregister;
  197. const usableregs:Tsupregset;
  198. var unusedregs:Tsupregset;
  199. var countunusedregs:byte);
  200. {$ifdef TEMPREGDEBUG}
  201. reg_user : regvar_ptreearray;
  202. reg_releaser : regvar_ptreearray;
  203. {$endif TEMPREGDEBUG}
  204. {$ifdef TEMPREGDEBUG}
  205. procedure testregisters;
  206. {$endif TEMPREGDEBUGx}
  207. end;
  208. const
  209. {# This value is used in tsaved. If the array value is equal
  210. to this, then this means that this register is not used.
  211. }
  212. reg_not_saved = $7fffffff;
  213. var
  214. {# This is the class instance used to access the register allocator class }
  215. rg: trgobj;
  216. { trerefence handling }
  217. {# Clear to zero a treference }
  218. procedure reference_reset(var ref : treference);
  219. {# Clear to zero a treference, and set is base address
  220. to base register.
  221. }
  222. procedure reference_reset_base(var ref : treference;base : tregister;offset : longint);
  223. procedure reference_reset_symbol(var ref : treference;sym : tasmsymbol;offset : longint);
  224. procedure reference_release(list: taasmoutput; const ref : treference);
  225. { This routine verifies if two references are the same, and
  226. if so, returns TRUE, otherwise returns false.
  227. }
  228. function references_equal(sref : treference;dref : treference) : boolean;
  229. { tlocation handling }
  230. procedure location_reset(var l : tlocation;lt:TLoc;lsize:TCGSize);
  231. procedure location_release(list: taasmoutput; const l : tlocation);
  232. procedure location_freetemp(list: taasmoutput; const l : tlocation);
  233. procedure location_copy(var destloc,sourceloc : tlocation);
  234. procedure location_swap(var destloc,sourceloc : tlocation);
  235. type
  236. psavedstate = ^tsavedstate;
  237. tsavedstate = record
  238. unusedregsint,usableregsint : Tsupregset;
  239. unusedregsaddr,usableregsaddr : Tsupregset;
  240. unusedregsfpu,usableregsfpu : tregisterset;
  241. unusedregsmm,usableregsmm : tregisterset;
  242. countunusedregsint,
  243. countunusedregsaddr,
  244. countunusedregsfpu,
  245. countunusedregsmm : byte;
  246. countusableregsint,
  247. countusableregsfpu,
  248. countusableregsmm : byte;
  249. { contains the registers which are really used by the proc itself }
  250. usedbyproc,
  251. usedinproc : tregisterset;
  252. reg_pushes : regvar_longintarray;
  253. is_reg_var : regvar_booleanarray;
  254. is_reg_var_int : Tsupregset;
  255. regvar_loaded: regvar_booleanarray;
  256. regvar_loaded_int: Tsupregset;
  257. {$ifdef TEMPREGDEBUG}
  258. reg_user : regvar_ptreearray;
  259. reg_releaser : regvar_ptreearray;
  260. {$endif TEMPREGDEBUG}
  261. end;
  262. punusedstate = ^tunusedstate;
  263. tunusedstate = record
  264. unusedregsint : Tsupregset;
  265. unusedregsaddr : Tsupregset;
  266. unusedregsfpu : tregisterset;
  267. unusedregsmm : tregisterset;
  268. countunusedregsint,
  269. countunusedregsaddr,
  270. countunusedregsfpu,
  271. countunusedregsmm : byte;
  272. end;
  273. implementation
  274. uses
  275. systems,
  276. globals,verbose,
  277. cgobj,tgobj,regvars;
  278. constructor trgobj.create;
  279. begin
  280. usedinproc := [];
  281. usedbyproc:=[];
  282. t_times := 0;
  283. resetusableregisters;
  284. {$ifdef TEMPREGDEBUG}
  285. fillchar(reg_user,sizeof(reg_user),0);
  286. fillchar(reg_releaser,sizeof(reg_releaser),0);
  287. {$endif TEMPREGDEBUG}
  288. end;
  289. function trgobj.getregistergen(list: taasmoutput; const lowreg, highreg: Toldregister;
  290. var unusedregs: tregisterset; var countunusedregs: byte): tregister;
  291. var
  292. i: Toldregister;
  293. r: Tregister;
  294. begin
  295. for i:=lowreg to highreg do
  296. begin
  297. if i in unusedregs then
  298. begin
  299. exclude(unusedregs,i);
  300. include(usedinproc,i);
  301. include(usedbyproc,i);
  302. dec(countunusedregs);
  303. r.enum:=i;
  304. list.concat(tai_regalloc.alloc(r));
  305. result := r;
  306. exit;
  307. end;
  308. end;
  309. internalerror(10);
  310. end;
  311. function Trgobj.getregistergenint(list:Taasmoutput;
  312. subreg:Tsubregister;
  313. const lowreg,highreg:Tsuperregister;
  314. var fusedinproc,fusedbyproc,unusedregs:Tsupregset;
  315. var countunusedregs:byte):Tregister;
  316. var i:Tsuperregister;
  317. r:Tregister;
  318. begin
  319. for i:=lowreg to highreg do
  320. begin
  321. if i in unusedregs then
  322. begin
  323. exclude(unusedregs,i);
  324. include(fusedinproc,i);
  325. include(fusedbyproc,i);
  326. dec(countunusedregs);
  327. r.enum:=R_INTREGISTER;
  328. r.number:=i shl 8 or subreg;
  329. list.concat(tai_regalloc.alloc(r));
  330. result:=r;
  331. exit;
  332. end;
  333. end;
  334. internalerror(10);
  335. end;
  336. procedure trgobj.ungetregistergen(list: taasmoutput; const r: tregister;
  337. const usableregs: tregisterset; var unusedregs: tregisterset; var countunusedregs: byte);
  338. begin
  339. if r.enum>lastreg then
  340. internalerror(2003010801);
  341. { takes much time }
  342. if not(r.enum in usableregs) then
  343. exit;
  344. {$ifdef TEMPREGDEBUG}
  345. if (r.enum in unusedregs) then
  346. {$ifdef EXTTEMPREGDEBUG}
  347. begin
  348. Comment(V_Debug,'register freed twice '+std_reg2str[r.enum]);
  349. testregisters32;
  350. exit;
  351. end
  352. {$else EXTTEMPREGDEBUG}
  353. exit
  354. {$endif EXTTEMPREGDEBUG}
  355. else
  356. {$endif TEMPREGDEBUG}
  357. inc(countunusedregs);
  358. include(unusedregs,r.enum);
  359. list.concat(tai_regalloc.dealloc(r));
  360. end;
  361. procedure trgobj.ungetregistergenint(list:taasmoutput;const r:Tregister;
  362. const usableregs:Tsupregset;
  363. var unusedregs:Tsupregset;
  364. var countunusedregs:byte);
  365. var supreg:Tsuperregister;
  366. begin
  367. if r.enum<=lastreg then
  368. internalerror(2003010803);
  369. supreg:=r.number shr 8;
  370. { takes much time }
  371. if not(supreg in usableregs) then
  372. exit;
  373. {$ifdef TEMPREGDEBUG}
  374. if (supreg in unusedregs) then
  375. {$ifdef EXTTEMPREGDEBUG}
  376. begin
  377. comment(v_debug,'register freed twice '+supreg_name(supreg));
  378. testregisters32;
  379. exit;
  380. end
  381. {$else EXTTEMPREGDEBUG}
  382. exit
  383. {$endif EXTTEMPREGDEBUG}
  384. else
  385. {$endif TEMPREGDEBUG}
  386. inc(countunusedregs);
  387. include(unusedregs,supreg);
  388. list.concat(tai_regalloc.dealloc(r));
  389. end;
  390. function trgobj.getregisterint(list:taasmoutput;size:Tcgsize):Tregister;
  391. var subreg:Tsubregister;
  392. begin
  393. if countunusedregsint=0 then
  394. internalerror(10);
  395. {$ifdef TEMPREGDEBUG}
  396. if curptree^^.usableregs-countunusedregsint>curptree^^.registers32 then
  397. internalerror(10);
  398. {$endif TEMPREGDEBUG}
  399. {$ifdef EXTTEMPREGDEBUG}
  400. if curptree^^.usableregs-countunusedregsint>curptree^^.reallyusedregs then
  401. curptree^^.reallyusedregs:=curptree^^.usableregs-countunusedregsint;
  402. {$endif EXTTEMPREGDEBUG}
  403. subreg:=cgsize2subreg(size);
  404. result:=getregistergenint(list,
  405. subreg,
  406. first_supreg,
  407. last_supreg,
  408. usedintbyproc,
  409. usedintinproc,
  410. unusedregsint,
  411. countunusedregsint);
  412. {$ifdef TEMPREGDEBUG}
  413. reg_user[result]:=curptree^;
  414. testregisters32;
  415. {$endif TEMPREGDEBUG}
  416. end;
  417. procedure trgobj.ungetregisterint(list : taasmoutput; r : tregister);
  418. begin
  419. ungetregistergenint(list,r,usableregsint,unusedregsint,
  420. countunusedregsint);
  421. {$ifdef TEMPREGDEBUG}
  422. reg_releaser[r]:=curptree^;
  423. testregisters32;
  424. {$endif TEMPREGDEBUG}
  425. end;
  426. { tries to allocate the passed register, if possible }
  427. function trgobj.getexplicitregisterint(list:Taasmoutput;r:Tnewregister):Tregister;
  428. var r2:Tregister;
  429. begin
  430. if (r shr 8) in unusedregsint then
  431. begin
  432. dec(countunusedregsint);
  433. {$ifdef TEMPREGDEBUG}
  434. if curptree^^.usableregs-countunusedregsint>curptree^^.registers32 then
  435. internalerror(10);
  436. reg_user[r shr 8]:=curptree^;
  437. {$endif TEMPREGDEBUG}
  438. exclude(unusedregsint,r shr 8);
  439. include(usedintinproc,r shr 8);
  440. include(usedintbyproc,r shr 8);
  441. r2.enum:=R_INTREGISTER;
  442. r2.number:=r;
  443. list.concat(tai_regalloc.alloc(r2));
  444. getexplicitregisterint:=r2;
  445. {$ifdef TEMPREGDEBUG}
  446. testregisters32;
  447. {$endif TEMPREGDEBUG}
  448. end
  449. else
  450. { getexplicitregisterint:=getregisterint(list,r and $ff);}
  451. internalerror(200301103);
  452. end;
  453. { tries to allocate the passed register, if possible }
  454. function trgobj.getexplicitregisterfpu(list : taasmoutput; r : Toldregister) : tregister;
  455. var r2:Tregister;
  456. begin
  457. if r in unusedregsfpu then
  458. begin
  459. dec(countunusedregsfpu);
  460. {$ifdef TEMPREGDEBUG}
  461. if curptree^^.usableregs-countunusedregsint>curptree^^.registers32 then
  462. internalerror(10);
  463. reg_user[r]:=curptree^;
  464. {$endif TEMPREGDEBUG}
  465. exclude(unusedregsfpu,r);
  466. include(usedinproc,r);
  467. include(usedbyproc,r);
  468. r2.enum:=r;
  469. list.concat(tai_regalloc.alloc(r2));
  470. getexplicitregisterfpu:=r2;
  471. {$ifdef TEMPREGDEBUG}
  472. testregisters32;
  473. {$endif TEMPREGDEBUG}
  474. end
  475. else
  476. getexplicitregisterfpu:=getregisterfpu(list);
  477. end;
  478. function trgobj.getregisterfpu(list: taasmoutput) : tregister;
  479. begin
  480. if countunusedregsfpu=0 then
  481. internalerror(10);
  482. result := getregistergen(list,firstsavefpureg,lastsavefpureg,
  483. unusedregsfpu,countunusedregsfpu);
  484. end;
  485. procedure trgobj.ungetregisterfpu(list : taasmoutput; r : tregister);
  486. begin
  487. ungetregistergen(list,r,usableregsfpu,unusedregsfpu,
  488. countunusedregsfpu);
  489. end;
  490. function trgobj.getregistermm(list: taasmoutput) : tregister;
  491. begin
  492. if countunusedregsmm=0 then
  493. internalerror(10);
  494. result := getregistergen(list,firstsavemmreg,lastsavemmreg,
  495. unusedregsmm,countunusedregsmm);
  496. end;
  497. procedure trgobj.ungetregistermm(list: taasmoutput; r: tregister);
  498. begin
  499. ungetregistergen(list,r,usableregsmm,unusedregsmm,
  500. countunusedregsmm);
  501. end;
  502. function trgobj.getaddressregister(list:Taasmoutput): tregister;
  503. begin
  504. {An address register is OS_INT per definition.}
  505. result := getregisterint(list,OS_INT);
  506. end;
  507. procedure trgobj.ungetaddressregister(list: taasmoutput; r: tregister);
  508. begin
  509. ungetregisterint(list,r);
  510. end;
  511. function trgobj.isaddressregister(reg: tregister): boolean;
  512. begin
  513. result := true;
  514. end;
  515. procedure trgobj.ungetregister(list: taasmoutput; r : tregister);
  516. begin
  517. if r.enum=R_NO then
  518. exit;
  519. if r.enum>lastreg then
  520. internalerror(200301081);
  521. if r.enum in intregs then
  522. ungetregisterint(list,r)
  523. else if r.enum in fpuregs then
  524. ungetregisterfpu(list,r)
  525. else if r.enum in mmregs then
  526. ungetregistermm(list,r)
  527. else if r.enum in addrregs then
  528. ungetaddressregister(list,r)
  529. else internalerror(2002070602);
  530. end;
  531. procedure trgobj.cleartempgen;
  532. begin
  533. countunusedregsint:=countusableregsint;
  534. countunusedregsfpu:=countusableregsfpu;
  535. countunusedregsmm:=countusableregsmm;
  536. unusedregsint:=usableregsint;
  537. unusedregsfpu:=usableregsfpu;
  538. unusedregsmm:=usableregsmm;
  539. end;
  540. procedure trgobj.ungetreference(list : taasmoutput; const ref : treference);
  541. begin
  542. ungetregister(list,ref.base);
  543. ungetregister(list,ref.index);
  544. end;
  545. procedure trgobj.saveintregvars(list:Taasmoutput;const s:Tsupregset);
  546. var r:Tsuperregister;
  547. begin
  548. if not(cs_regalloc in aktglobalswitches) then
  549. exit;
  550. for r:=firstsaveintreg to lastsaveintreg do
  551. if (r in is_reg_var_int) and
  552. (r in s) then
  553. store_regvar_int(list,r);
  554. end;
  555. procedure trgobj.saveotherregvars(list: taasmoutput; const s: tregisterset);
  556. var
  557. r: Tregister;
  558. begin
  559. if not(cs_regalloc in aktglobalswitches) then
  560. exit;
  561. if firstsavefpureg <> R_NO then
  562. for r.enum := firstsavefpureg to lastsavefpureg do
  563. if is_reg_var[r.enum] and
  564. (r.enum in s) then
  565. store_regvar(list,r);
  566. if firstsavemmreg <> R_NO then
  567. for r.enum := firstsavemmreg to lastsavemmreg do
  568. if is_reg_var[r.enum] and
  569. (r.enum in s) then
  570. store_regvar(list,r);
  571. end;
  572. procedure trgobj.saveusedintregisters(list:Taasmoutput;
  573. var saved:Tpushedsavedint;
  574. const s:Tsupregset);
  575. var r:Tsuperregister;
  576. r2:Tregister;
  577. hr : treference;
  578. begin
  579. usedintinproc:=usedintinproc+s;
  580. for r:=firstsaveintreg to lastsaveintreg do
  581. begin
  582. saved[r].ofs:=reg_not_saved;
  583. { if the register is used by the calling subroutine and if }
  584. { it's not a regvar (those are handled separately) }
  585. if not (r in is_reg_var_int) and
  586. (r in s) and
  587. { and is present in use }
  588. not(r in unusedregsint) then
  589. begin
  590. { then save it }
  591. tg.GetTemp(list,sizeof(aword),tt_persistant,hr);
  592. saved[r].ofs:=hr.offset;
  593. r2.enum:=R_INTREGISTER;
  594. r2.number:=r shl 8 or R_SUBWHOLE;
  595. cg.a_load_reg_ref(list,OS_INT,r2,hr);
  596. cg.a_reg_dealloc(list,r2);
  597. include(unusedregsint,r);
  598. inc(countunusedregsint);
  599. end;
  600. end;
  601. {$ifdef TEMPREGDEBUG}
  602. testregisters32;
  603. {$endif TEMPREGDEBUG}
  604. end;
  605. procedure trgobj.saveusedotherregisters(list: taasmoutput;
  606. var saved : tpushedsaved; const s: tregisterset);
  607. var
  608. r : tregister;
  609. hr : treference;
  610. begin
  611. usedinproc:=usedinproc + s;
  612. { don't try to save the fpu registers if not desired (e.g. for }
  613. { the 80x86) }
  614. if firstsavefpureg <> R_NO then
  615. for r.enum:=firstsavefpureg to lastsavefpureg do
  616. begin
  617. saved[r.enum].ofs:=reg_not_saved;
  618. { if the register is used by the calling subroutine and if }
  619. { it's not a regvar (those are handled separately) }
  620. if not is_reg_var[r.enum] and
  621. (r.enum in s) and
  622. { and is present in use }
  623. not(r.enum in unusedregsfpu) then
  624. begin
  625. { then save it }
  626. tg.GetTemp(list,extended_size,tt_persistant,hr);
  627. saved[r.enum].ofs:=hr.offset;
  628. cg.a_loadfpu_reg_ref(list,OS_FLOAT,r,hr);
  629. cg.a_reg_dealloc(list,r);
  630. include(unusedregsfpu,r.enum);
  631. inc(countunusedregsfpu);
  632. end;
  633. end;
  634. { don't save the vector registers if there's no support for them }
  635. if firstsavemmreg <> R_NO then
  636. for r.enum:=firstsavemmreg to lastsavemmreg do
  637. begin
  638. saved[r.enum].ofs:=reg_not_saved;
  639. { if the register is in use and if it's not a regvar (those }
  640. { are handled separately), save it }
  641. if not is_reg_var[r.enum] and
  642. (r.enum in s) and
  643. { and is present in use }
  644. not(r.enum in unusedregsmm) then
  645. begin
  646. { then save it }
  647. tg.GetTemp(list,mmreg_size,tt_persistant,hr);
  648. saved[r.enum].ofs:=hr.offset;
  649. cg.a_loadmm_reg_ref(list,r,hr);
  650. cg.a_reg_dealloc(list,r);
  651. include(unusedregsmm,r.enum);
  652. inc(countunusedregsmm);
  653. end;
  654. end;
  655. {$ifdef TEMPREGDEBUG}
  656. testregisters32;
  657. {$endif TEMPREGDEBUG}
  658. end;
  659. procedure trgobj.restoreusedintregisters(list:Taasmoutput;
  660. const saved:Tpushedsavedint);
  661. var r:Tsuperregister;
  662. r2:Tregister;
  663. hr:Treference;
  664. begin
  665. for r:=lastsaveintreg downto firstsaveintreg do
  666. begin
  667. if saved[r].ofs <> reg_not_saved then
  668. begin
  669. r2.enum:=R_INTREGISTER;
  670. r2.number:=NR_FRAME_POINTER_REG;
  671. reference_reset_base(hr,r2,saved[r].ofs);
  672. r2.enum:=R_INTREGISTER;
  673. r2.number:=r shl 8 or R_SUBWHOLE;
  674. cg.a_reg_alloc(list,r2);
  675. cg.a_load_ref_reg(list,OS_INT,hr,r2);
  676. if not (r in unusedregsint) then
  677. { internalerror(10)
  678. in n386cal we always save/restore the reg *state*
  679. using save/restoreunusedstate -> the current state
  680. may not be real (JM) }
  681. else
  682. begin
  683. dec(countunusedregsint);
  684. exclude(unusedregsint,r);
  685. end;
  686. tg.UnGetTemp(list,hr);
  687. end;
  688. end;
  689. {$ifdef TEMPREGDEBUG}
  690. testregisters32;
  691. {$endif TEMPREGDEBUG}
  692. end;
  693. procedure trgobj.restoreusedotherregisters(list : taasmoutput;
  694. const saved : tpushedsaved);
  695. var
  696. r,r2 : tregister;
  697. hr : treference;
  698. begin
  699. if firstsavemmreg <> R_NO then
  700. for r.enum:=lastsavemmreg downto firstsavemmreg do
  701. begin
  702. if saved[r.enum].ofs <> reg_not_saved then
  703. begin
  704. r2.enum:=R_INTREGISTER;
  705. r2.number:=NR_FRAME_POINTER_REG;
  706. reference_reset_base(hr,r2,saved[r.enum].ofs);
  707. cg.a_reg_alloc(list,r);
  708. cg.a_loadmm_ref_reg(list,hr,r);
  709. if not (r.enum in unusedregsmm) then
  710. { internalerror(10)
  711. in n386cal we always save/restore the reg *state*
  712. using save/restoreunusedstate -> the current state
  713. may not be real (JM) }
  714. else
  715. begin
  716. dec(countunusedregsmm);
  717. exclude(unusedregsmm,r.enum);
  718. end;
  719. tg.UnGetTemp(list,hr);
  720. end;
  721. end;
  722. if firstsavefpureg <> R_NO then
  723. for r.enum:=lastsavefpureg downto firstsavefpureg do
  724. begin
  725. if saved[r.enum].ofs <> reg_not_saved then
  726. begin
  727. r2.enum:=R_INTREGISTER;
  728. r2.number:=NR_FRAME_POINTER_REG;
  729. reference_reset_base(hr,r2,saved[r.enum].ofs);
  730. cg.a_reg_alloc(list,r);
  731. cg.a_loadfpu_ref_reg(list,OS_FLOAT,hr,r);
  732. if not (r.enum in unusedregsfpu) then
  733. { internalerror(10)
  734. in n386cal we always save/restore the reg *state*
  735. using save/restoreunusedstate -> the current state
  736. may not be real (JM) }
  737. else
  738. begin
  739. dec(countunusedregsfpu);
  740. exclude(unusedregsfpu,r.enum);
  741. end;
  742. tg.UnGetTemp(list,hr);
  743. end;
  744. end;
  745. {$ifdef TEMPREGDEBUG}
  746. testregisters32;
  747. {$endif TEMPREGDEBUG}
  748. end;
  749. procedure trgobj.incrementintregisterpushed(const s:Tsupregset);
  750. var regi:Tsuperregister;
  751. begin
  752. for regi:=firstsaveintreg to lastsaveintreg do
  753. begin
  754. if (regi in s) then
  755. inc(reg_pushes_int[regi],t_times*2);
  756. end;
  757. end;
  758. procedure trgobj.incrementotherregisterpushed(const s:Tregisterset);
  759. var
  760. regi : Toldregister;
  761. begin
  762. if firstsavefpureg <> R_NO then
  763. for regi:=firstsavefpureg to lastsavefpureg do
  764. begin
  765. if (regi in s) then
  766. inc(reg_pushes[regi],t_times*2);
  767. end;
  768. if firstsavemmreg <> R_NO then
  769. for regi:=firstsavemmreg to lastsavemmreg do
  770. begin
  771. if (regi in s) then
  772. inc(reg_pushes[regi],t_times*2);
  773. end;
  774. end;
  775. procedure trgobj.clearregistercount;
  776. begin
  777. fillchar(reg_pushes,sizeof(reg_pushes),0);
  778. fillchar(is_reg_var,sizeof(is_reg_var),false);
  779. is_reg_var_int:=[];
  780. fillchar(regvar_loaded,sizeof(regvar_loaded),false);
  781. regvar_loaded_int:=[];
  782. end;
  783. procedure trgobj.resetusableregisters;
  784. begin
  785. { initialize fields with constant values from cpubase }
  786. countusableregsint := cpubase.c_countusableregsint;
  787. countusableregsfpu := cpubase.c_countusableregsfpu;
  788. countusableregsmm := cpubase.c_countusableregsmm;
  789. usableregsint := cpubase.usableregsint;
  790. usableregsfpu := cpubase.usableregsfpu;
  791. usableregsmm := cpubase.usableregsmm;
  792. clearregistercount;
  793. end;
  794. procedure trgobj.makeregvarint(reg:Tnewregister);
  795. var supreg:Tsuperregister;
  796. begin
  797. supreg:=reg shr 8;
  798. dec(countusableregsint);
  799. dec(countunusedregsint);
  800. exclude(usableregsint,reg);
  801. exclude(unusedregsint,reg);
  802. include(is_reg_var_int,supreg);
  803. end;
  804. procedure trgobj.makeregvarother(reg: tregister);
  805. begin
  806. if reg.enum>lastreg then
  807. internalerror(200301081);
  808. if reg.enum in intregs then
  809. internalerror(200301151)
  810. else if reg.enum in fpuregs then
  811. begin
  812. dec(countusableregsfpu);
  813. dec(countunusedregsfpu);
  814. exclude(usableregsfpu,reg.enum);
  815. exclude(unusedregsfpu,reg.enum);
  816. end
  817. else if reg.enum in mmregs then
  818. begin
  819. dec(countusableregsmm);
  820. dec(countunusedregsmm);
  821. exclude(usableregsmm,reg.enum);
  822. exclude(unusedregsmm,reg.enum);
  823. end;
  824. is_reg_var[reg.enum]:=true;
  825. end;
  826. {$ifdef TEMPREGDEBUG}
  827. procedure trgobj.testregisters;
  828. var
  829. r: tregister;
  830. test : byte;
  831. begin
  832. test:=0;
  833. for r := firstsaveintreg to lastsaveintreg do
  834. inc(test,ord(r in unusedregsint));
  835. if test<>countunusedregsint then
  836. internalerror(10);
  837. end;
  838. {$endif TEMPREGDEBUG}
  839. procedure trgobj.saveStateForInline(var state: pointer);
  840. begin
  841. new(psavedstate(state));
  842. psavedstate(state)^.unusedregsint := unusedregsint;
  843. psavedstate(state)^.usableregsint := usableregsint;
  844. psavedstate(state)^.unusedregsfpu := unusedregsfpu;
  845. psavedstate(state)^.usableregsfpu := usableregsfpu;
  846. psavedstate(state)^.unusedregsmm := unusedregsmm;
  847. psavedstate(state)^.usableregsmm := usableregsmm;
  848. psavedstate(state)^.countunusedregsint := countunusedregsint;
  849. psavedstate(state)^.countunusedregsfpu := countunusedregsfpu;
  850. psavedstate(state)^.countunusedregsmm := countunusedregsmm;
  851. psavedstate(state)^.countusableregsint := countusableregsint;
  852. psavedstate(state)^.countusableregsfpu := countusableregsfpu;
  853. psavedstate(state)^.countusableregsmm := countusableregsmm;
  854. psavedstate(state)^.usedinproc := usedinproc;
  855. psavedstate(state)^.usedbyproc := usedbyproc;
  856. psavedstate(state)^.reg_pushes := reg_pushes;
  857. psavedstate(state)^.is_reg_var := is_reg_var;
  858. psavedstate(state)^.is_reg_var_int := is_reg_var_int;
  859. psavedstate(state)^.regvar_loaded := regvar_loaded;
  860. psavedstate(state)^.regvar_loaded_int := regvar_loaded_int;
  861. {$ifdef TEMPREGDEBUG}
  862. psavedstate(state)^.reg_user := reg_user;
  863. psavedstate(state)^.reg_releaser := reg_releaser;
  864. {$endif TEMPREGDEBUG}
  865. end;
  866. procedure trgobj.restoreStateAfterInline(var state: pointer);
  867. begin
  868. unusedregsint := psavedstate(state)^.unusedregsint;
  869. usableregsint := psavedstate(state)^.usableregsint;
  870. unusedregsfpu := psavedstate(state)^.unusedregsfpu;
  871. usableregsfpu := psavedstate(state)^.usableregsfpu;
  872. unusedregsmm := psavedstate(state)^.unusedregsmm;
  873. usableregsmm := psavedstate(state)^.usableregsmm;
  874. countunusedregsint := psavedstate(state)^.countunusedregsint;
  875. countunusedregsfpu := psavedstate(state)^.countunusedregsfpu;
  876. countunusedregsmm := psavedstate(state)^.countunusedregsmm;
  877. countusableregsint := psavedstate(state)^.countusableregsint;
  878. countusableregsfpu := psavedstate(state)^.countusableregsfpu;
  879. countusableregsmm := psavedstate(state)^.countusableregsmm;
  880. usedinproc := psavedstate(state)^.usedinproc;
  881. usedbyproc := psavedstate(state)^.usedbyproc;
  882. reg_pushes := psavedstate(state)^.reg_pushes;
  883. is_reg_var := psavedstate(state)^.is_reg_var;
  884. is_reg_var_int := psavedstate(state)^.is_reg_var_int;
  885. regvar_loaded := psavedstate(state)^.regvar_loaded;
  886. regvar_loaded_int := psavedstate(state)^.regvar_loaded_int;
  887. {$ifdef TEMPREGDEBUG}
  888. reg_user := psavedstate(state)^.reg_user;
  889. reg_releaser := psavedstate(state)^.reg_releaser;
  890. {$endif TEMPREGDEBUG}
  891. dispose(psavedstate(state));
  892. state := nil;
  893. end;
  894. procedure trgobj.saveUnusedState(var state: pointer);
  895. begin
  896. new(punusedstate(state));
  897. punusedstate(state)^.unusedregsint := unusedregsint;
  898. punusedstate(state)^.unusedregsfpu := unusedregsfpu;
  899. punusedstate(state)^.unusedregsmm := unusedregsmm;
  900. punusedstate(state)^.countunusedregsint := countunusedregsint;
  901. punusedstate(state)^.countunusedregsfpu := countunusedregsfpu;
  902. punusedstate(state)^.countunusedregsmm := countunusedregsmm;
  903. end;
  904. procedure trgobj.restoreUnusedState(var state: pointer);
  905. begin
  906. unusedregsint := punusedstate(state)^.unusedregsint;
  907. unusedregsfpu := punusedstate(state)^.unusedregsfpu;
  908. unusedregsmm := punusedstate(state)^.unusedregsmm;
  909. countunusedregsint := punusedstate(state)^.countunusedregsint;
  910. countunusedregsfpu := punusedstate(state)^.countunusedregsfpu;
  911. countunusedregsmm := punusedstate(state)^.countunusedregsmm;
  912. dispose(punusedstate(state));
  913. state := nil;
  914. end;
  915. {****************************************************************************
  916. TReference
  917. ****************************************************************************}
  918. procedure reference_reset(var ref : treference);
  919. begin
  920. FillChar(ref,sizeof(treference),0);
  921. ref.base.enum:=R_INTREGISTER;
  922. ref.index.enum:=R_INTREGISTER;
  923. {$ifdef i386}
  924. ref.segment.enum:=R_INTREGISTER;
  925. {$endif}
  926. end;
  927. procedure reference_reset_base(var ref : treference;base : tregister;offset : longint);
  928. begin
  929. reference_reset(ref);
  930. ref.base:=base;
  931. ref.offset:=offset;
  932. end;
  933. procedure reference_reset_symbol(var ref : treference;sym : tasmsymbol;offset : longint);
  934. begin
  935. reference_reset(ref);
  936. ref.symbol:=sym;
  937. ref.offset:=offset;
  938. end;
  939. procedure reference_release(list: taasmoutput; const ref : treference);
  940. begin
  941. rg.ungetreference(list,ref);
  942. end;
  943. function references_equal(sref : treference;dref : treference):boolean;
  944. begin
  945. references_equal:=CompareByte(sref,dref,sizeof(treference))=0;
  946. end;
  947. { on most processors , this routine does nothing, overriden currently }
  948. { only by 80x86 processor. }
  949. function trgobj.makeregsize(reg: tregister; size: tcgsize): tregister;
  950. begin
  951. makeregsize := reg;
  952. end;
  953. {****************************************************************************
  954. TLocation
  955. ****************************************************************************}
  956. procedure location_reset(var l : tlocation;lt:TLoc;lsize:TCGSize);
  957. begin
  958. FillChar(l,sizeof(tlocation),0);
  959. l.loc:=lt;
  960. l.size:=lsize;
  961. case l.loc of
  962. LOC_REGISTER,LOC_CREGISTER:
  963. begin
  964. l.register.enum:=R_INTREGISTER;
  965. l.registerhigh.enum:=R_INTREGISTER;
  966. end;
  967. LOC_REFERENCE,LOC_CREFERENCE:
  968. begin
  969. l.reference.base.enum:=R_INTREGISTER;
  970. l.reference.index.enum:=R_INTREGISTER;
  971. {$ifdef i386}
  972. l.reference.segment.enum:=R_INTREGISTER;
  973. {$endif}
  974. end;
  975. end;
  976. end;
  977. procedure location_release(list: taasmoutput; const l : tlocation);
  978. begin
  979. case l.loc of
  980. LOC_REGISTER,LOC_CREGISTER :
  981. begin
  982. rg.ungetregisterint(list,l.register);
  983. if l.size in [OS_64,OS_S64] then
  984. rg.ungetregisterint(list,l.registerhigh);
  985. end;
  986. LOC_CREFERENCE,LOC_REFERENCE :
  987. rg.ungetreference(list, l.reference);
  988. end;
  989. end;
  990. procedure location_freetemp(list:taasmoutput; const l : tlocation);
  991. begin
  992. if (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  993. tg.ungetiftemp(list,l.reference);
  994. end;
  995. procedure location_copy(var destloc,sourceloc : tlocation);
  996. begin
  997. destloc:=sourceloc;
  998. end;
  999. procedure location_swap(var destloc,sourceloc : tlocation);
  1000. var
  1001. swapl : tlocation;
  1002. begin
  1003. swapl := destloc;
  1004. destloc := sourceloc;
  1005. sourceloc := swapl;
  1006. end;
  1007. initialization
  1008. ;
  1009. finalization
  1010. rg.free;
  1011. end.
  1012. {
  1013. $Log$
  1014. Revision 1.23 2003-02-19 22:00:14 daniel
  1015. * Code generator converted to new register notation
  1016. - Horribily outdated todo.txt removed
  1017. Revision 1.22 2003/02/02 19:25:54 carl
  1018. * Several bugfixes for m68k target (register alloc., opcode emission)
  1019. + VIS target
  1020. + Generic add more complete (still not verified)
  1021. Revision 1.21 2003/01/08 18:43:57 daniel
  1022. * Tregister changed into a record
  1023. Revision 1.20 2002/10/05 12:43:28 carl
  1024. * fixes for Delphi 6 compilation
  1025. (warning : Some features do not work under Delphi)
  1026. Revision 1.19 2002/08/23 16:14:49 peter
  1027. * tempgen cleanup
  1028. * tt_noreuse temp type added that will be used in genentrycode
  1029. Revision 1.18 2002/08/17 22:09:47 florian
  1030. * result type handling in tcgcal.pass_2 overhauled
  1031. * better tnode.dowrite
  1032. * some ppc stuff fixed
  1033. Revision 1.17 2002/08/17 09:23:42 florian
  1034. * first part of procinfo rewrite
  1035. Revision 1.16 2002/08/06 20:55:23 florian
  1036. * first part of ppc calling conventions fix
  1037. Revision 1.15 2002/08/05 18:27:48 carl
  1038. + more more more documentation
  1039. + first version include/exclude (can't test though, not enough scratch for i386 :()...
  1040. Revision 1.14 2002/08/04 19:06:41 carl
  1041. + added generic exception support (still does not work!)
  1042. + more documentation
  1043. Revision 1.13 2002/07/07 09:52:32 florian
  1044. * powerpc target fixed, very simple units can be compiled
  1045. * some basic stuff for better callparanode handling, far from being finished
  1046. Revision 1.12 2002/07/01 18:46:26 peter
  1047. * internal linker
  1048. * reorganized aasm layer
  1049. Revision 1.11 2002/05/18 13:34:17 peter
  1050. * readded missing revisions
  1051. Revision 1.10 2002/05/16 19:46:44 carl
  1052. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1053. + try to fix temp allocation (still in ifdef)
  1054. + generic constructor calls
  1055. + start of tassembler / tmodulebase class cleanup
  1056. Revision 1.8 2002/04/21 15:23:03 carl
  1057. + makeregsize
  1058. + changeregsize is now a local routine
  1059. Revision 1.7 2002/04/20 21:32:25 carl
  1060. + generic FPC_CHECKPOINTER
  1061. + first parameter offset in stack now portable
  1062. * rename some constants
  1063. + move some cpu stuff to other units
  1064. - remove unused constents
  1065. * fix stacksize for some targets
  1066. * fix generic size problems which depend now on EXTEND_SIZE constant
  1067. Revision 1.6 2002/04/15 19:03:31 carl
  1068. + reg2str -> std_reg2str()
  1069. Revision 1.5 2002/04/06 18:13:01 jonas
  1070. * several powerpc-related additions and fixes
  1071. Revision 1.4 2002/04/04 19:06:04 peter
  1072. * removed unused units
  1073. * use tlocation.size in cg.a_*loc*() routines
  1074. Revision 1.3 2002/04/02 17:11:29 peter
  1075. * tlocation,treference update
  1076. * LOC_CONSTANT added for better constant handling
  1077. * secondadd splitted in multiple routines
  1078. * location_force_reg added for loading a location to a register
  1079. of a specified size
  1080. * secondassignment parses now first the right and then the left node
  1081. (this is compatible with Kylix). This saves a lot of push/pop especially
  1082. with string operations
  1083. * adapted some routines to use the new cg methods
  1084. Revision 1.2 2002/04/01 19:24:25 jonas
  1085. * fixed different parameter name in interface and implementation
  1086. declaration of a method (only 1.0.x detected this)
  1087. Revision 1.1 2002/03/31 20:26:36 jonas
  1088. + a_loadfpu_* and a_loadmm_* methods in tcg
  1089. * register allocation is now handled by a class and is mostly processor
  1090. independent (+rgobj.pas and i386/rgcpu.pas)
  1091. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1092. * some small improvements and fixes to the optimizer
  1093. * some register allocation fixes
  1094. * some fpuvaroffset fixes in the unary minus node
  1095. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1096. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1097. also better optimizable)
  1098. * fixed and optimized register saving/restoring for new/dispose nodes
  1099. * LOC_FPU locations now also require their "register" field to be set to
  1100. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1101. - list field removed of the tnode class because it's not used currently
  1102. and can cause hard-to-find bugs
  1103. }