rgobj.pas 45 KB

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