rgobj.pas 46 KB

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