rgcpu.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the i386 specific class for the register
  5. allocator
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit rgcpu;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. cpubase,
  24. cpuinfo,
  25. aasmbase,aasmtai,aasmcpu,
  26. cclasses,globtype,cgbase,cginfo,rgobj;
  27. type
  28. trgcpu = class(trgobj)
  29. fpuvaroffset : byte;
  30. function getregisterfpu(list: taasmoutput;size:TCGSize) : tregister; override;
  31. procedure ungetregisterfpu(list: taasmoutput; r : tregister;size:TCGSize); override;
  32. {# Returns a subset register of the register r with the specified size.
  33. WARNING: There is no clearing of the upper parts of the register,
  34. if a 8-bit / 16-bit register is converted to a 32-bit register.
  35. It is up to the code generator to correctly zero fill the register
  36. }
  37. function makeregsize(reg: tregister; size: tcgsize): tregister; override;
  38. { pushes and restores registers }
  39. {$ifdef SUPPORT_MMX}
  40. procedure pushusedotherregisters(list:Taasmoutput;
  41. var pushed:Tpushedsavedother;
  42. const s:Totherregisterset);
  43. {$endif SUPPORT_MMX}
  44. {$ifdef SUPPORT_MMX}
  45. procedure popusedotherregisters(list:Taasmoutput;
  46. const pushed:Tpushedsavedother);
  47. {$endif SUPPORT_MMX}
  48. procedure saveusedotherregisters(list:Taasmoutput;
  49. var saved:Tpushedsavedother;
  50. const s:Totherregisterset);override;
  51. procedure restoreusedotherregisters(list:Taasmoutput;
  52. const saved:Tpushedsavedother);override;
  53. procedure resetusableregisters;override;
  54. { corrects the fpu stack register by ofs }
  55. function correct_fpuregister(r : tregister;ofs : byte) : tregister;
  56. end;
  57. implementation
  58. uses
  59. systems,
  60. globals,verbose,
  61. tgobj;
  62. function trgcpu.getregisterfpu(list: taasmoutput;size: TCGSize) : tregister;
  63. begin
  64. { note: don't return R_ST0, see comments above implementation of }
  65. { a_loadfpu_* methods in cgcpu (JM) }
  66. result:=NR_ST;
  67. end;
  68. procedure trgcpu.ungetregisterfpu(list : taasmoutput; r : tregister;size:TCGSize);
  69. begin
  70. { nothing to do, fpu stack management is handled by the load/ }
  71. { store operations in cgcpu (JM) }
  72. end;
  73. {$ifdef SUPPORT_MMX}
  74. procedure trgcpu.pushusedotherregisters(list:Taasmoutput;
  75. var pushed:Tpushedsavedother;
  76. const s:Totherregisterset);
  77. { var r:Toldregister;
  78. r2:Tregister;
  79. hr:Treference;}
  80. begin
  81. (* used_in_proc_other:=used_in_proc_other+s;
  82. for r:=R_MM0 to R_MM6 do
  83. begin
  84. pushed[r].pushed:=false;
  85. { if the register is used by the calling subroutine }
  86. if not is_reg_var_other[r] and
  87. (r in s) and
  88. { and is present in use }
  89. not(r in unusedregsmm) then
  90. begin
  91. r2.enum:=R_INTREGISTER;
  92. r2.number:=NR_ESP;
  93. list.concat(Taicpu.Op_const_reg(A_SUB,S_L,8,r2));
  94. reference_reset_base(hr,r2,0);
  95. r2.enum:=r;
  96. list.concat(Taicpu.Op_reg_ref(A_MOVQ,S_NO,r2,hr));
  97. include(unusedregsmm,r);
  98. pushed[r].pushed:=true;
  99. end;
  100. end;*)
  101. {$ifdef TEMPREGDEBUG}
  102. testregisters;
  103. {$endif TEMPREGDEBUG}
  104. end;
  105. {$endif SUPPORT_MMX}
  106. {$ifdef SUPPORT_MMX}
  107. procedure trgcpu.popusedotherregisters(list:Taasmoutput;
  108. const pushed:Tpushedsavedother);
  109. { var r:Toldregister;
  110. r2,r3:Tregister;
  111. hr:Treference;}
  112. begin
  113. { restore in reverse order: }
  114. { for r:=R_MM6 downto R_MM0 do
  115. if pushed[r].pushed then
  116. begin
  117. r2.enum:=R_INTREGISTER;
  118. r2.number:=NR_ESP;
  119. reference_reset_base(hr,r2,0);
  120. r3.enum:=r;
  121. list.concat(Taicpu.op_ref_reg(A_MOVQ,S_NO,hr,r3));
  122. list.concat(Taicpu.op_const_reg(A_ADD,S_L,8,r2));
  123. exclude(unusedregsmm,r);
  124. end;}
  125. {$ifdef TEMPREGDEBUG}
  126. testregisters;
  127. {$endif TEMPREGDEBUG}
  128. end;
  129. {$endif SUPPORT_MMX}
  130. procedure trgcpu.saveusedotherregisters(list:Taasmoutput;var saved:Tpushedsavedother;
  131. const s:totherregisterset);
  132. begin
  133. {$ifdef SUPPORT_MMX}
  134. if (aktoptprocessor in [class386,classP5]) or
  135. (CS_LittleSize in aktglobalswitches) then
  136. pushusedotherregisters(list,saved,s)
  137. else
  138. {$endif SUPPORT_MMX}
  139. inherited saveusedotherregisters(list,saved,s);
  140. end;
  141. procedure trgcpu.restoreusedotherregisters(list:Taasmoutput;
  142. const saved:tpushedsavedother);
  143. begin
  144. {$ifdef SUPPORT_MMX}
  145. if (aktoptprocessor in [class386,classP5]) or
  146. (CS_LittleSize in aktglobalswitches) then
  147. popusedotherregisters(list,saved)
  148. else
  149. {$endif SUPPORT_MMX}
  150. inherited restoreusedotherregisters(list,saved);
  151. end;
  152. procedure trgcpu.resetusableregisters;
  153. begin
  154. inherited resetusableregisters;
  155. fpuvaroffset := 0;
  156. end;
  157. function trgcpu.correct_fpuregister(r : tregister;ofs : byte) : tregister;
  158. begin
  159. correct_fpuregister:=r;
  160. setsupreg(correct_fpuregister,ofs);
  161. end;
  162. function trgcpu.makeregsize(reg: tregister; size: tcgsize): tregister;
  163. var
  164. subreg : tsubregister;
  165. begin
  166. if getregtype(reg)<>R_INTREGISTER then
  167. internalerror(200306032);
  168. subreg:=cgsize2subreg(size);
  169. result:=reg;
  170. setsubreg(result,subreg);
  171. add_constraints(result);
  172. end;
  173. end.
  174. {
  175. $Log$
  176. Revision 1.6 2003-09-24 17:12:02 florian
  177. * several fixes for new reg allocator
  178. Revision 1.5 2003/06/13 21:19:33 peter
  179. * current_procdef removed, use current_procinfo.procdef instead
  180. Revision 1.4 2002/04/25 20:15:40 florian
  181. * block nodes within expressions shouldn't release the used registers,
  182. fixed using a flag till the new rg is ready
  183. Revision 1.3 2003/01/05 13:36:54 florian
  184. * x86-64 compiles
  185. + very basic support for float128 type (x86-64 only)
  186. Revision 1.2 2002/07/25 22:55:34 florian
  187. * several fixes, small test units can be compiled
  188. Revision 1.1 2002/07/24 22:38:15 florian
  189. + initial release of x86-64 target code
  190. Revision 1.8 2002/07/01 18:46:34 peter
  191. * internal linker
  192. * reorganized aasm layer
  193. Revision 1.7 2002/05/16 19:46:52 carl
  194. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  195. + try to fix temp allocation (still in ifdef)
  196. + generic constructor calls
  197. + start of tassembler / tmodulebase class cleanup
  198. Revision 1.6 2002/05/12 16:53:18 peter
  199. * moved entry and exitcode to ncgutil and cgobj
  200. * foreach gets extra argument for passing local data to the
  201. iterator function
  202. * -CR checks also class typecasts at runtime by changing them
  203. into as
  204. * fixed compiler to cycle with the -CR option
  205. * fixed stabs with elf writer, finally the global variables can
  206. be watched
  207. * removed a lot of routines from cga unit and replaced them by
  208. calls to cgobj
  209. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  210. u32bit then the other is typecasted also to u32bit without giving
  211. a rangecheck warning/error.
  212. * fixed pascal calling method with reversing also the high tree in
  213. the parast, detected by tcalcst3 test
  214. Revision 1.5 2002/04/21 15:43:32 carl
  215. * changeregsize -> rg.makeregsize
  216. * changeregsize moved from cpubase to here
  217. Revision 1.4 2002/04/15 19:44:22 peter
  218. * fixed stackcheck that would be called recursively when a stack
  219. error was found
  220. * generic changeregsize(reg,size) for i386 register resizing
  221. * removed some more routines from cga unit
  222. * fixed returnvalue handling
  223. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  224. Revision 1.3 2002/04/04 19:06:13 peter
  225. * removed unused units
  226. * use tlocation.size in cg.a_*loc*() routines
  227. Revision 1.2 2002/04/02 17:11:39 peter
  228. * tlocation,treference update
  229. * LOC_CONSTANT added for better constant handling
  230. * secondadd splitted in multiple routines
  231. * location_force_reg added for loading a location to a register
  232. of a specified size
  233. * secondassignment parses now first the right and then the left node
  234. (this is compatible with Kylix). This saves a lot of push/pop especially
  235. with string operations
  236. * adapted some routines to use the new cg methods
  237. Revision 1.1 2002/03/31 20:26:40 jonas
  238. + a_loadfpu_* and a_loadmm_* methods in tcg
  239. * register allocation is now handled by a class and is mostly processor
  240. independent (+rgobj.pas and i386/rgcpu.pas)
  241. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  242. * some small improvements and fixes to the optimizer
  243. * some register allocation fixes
  244. * some fpuvaroffset fixes in the unary minus node
  245. * push/popusedregisters is now called rg.save/restoreusedregisters and
  246. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  247. also better optimizable)
  248. * fixed and optimized register saving/restoring for new/dispose nodes
  249. * LOC_FPU locations now also require their "register" field to be set to
  250. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  251. - list field removed of the tnode class because it's not used currently
  252. and can cause hard-to-find bugs
  253. }