rgobj.pas 45 KB

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