ncgutil.pas 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Helper routines for all code generators
  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. unit ncgutil;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node;
  23. type
  24. tloadregvars = (lr_dont_load_regvars, lr_load_regvars);
  25. {$ifdef TEMPS_NOT_PUSH}
  26. function maybe_savetotemp(needed : byte;p : tnode;isint64 : boolean) : boolean;
  27. procedure restorefromtemp(p : tnode;isint64 : boolean);
  28. {$endif TEMPS_NOT_PUSH}
  29. procedure maketojumpbool(p : tnode; loadregvars: tloadregvars);
  30. implementation
  31. uses
  32. globals,systems,verbose,
  33. types,
  34. aasm,cgbase,regvars,
  35. ncon,
  36. cpubase,tgobj,cpuinfo,cginfo,cgobj,cgcpu,rgobj,cg64f32;
  37. {$ifdef TEMPS_NOT_PUSH}
  38. function maybe_savetotemp(needed : byte;p : tnode;isint64 : boolean) : boolean;
  39. var
  40. href : treference;
  41. scratchreg : tregister;
  42. saved : boolean;
  43. begin
  44. if needed>rg.countunusedregsint then
  45. begin
  46. if (p.location.loc=LOC_REGISTER) then
  47. begin
  48. if isint64 then
  49. begin
  50. tg.gettempofsizereference(exprasmlist,8,href);
  51. p.temp_offset:=href.offset;
  52. { do we have a 64bit processor? }
  53. if sizeof(aword) < 8 then
  54. begin
  55. tcg64f32(cg).a_load64_reg_ref(exprasmlist,
  56. p.location.registerlow,p.location.registerhigh,
  57. href);
  58. rg.ungetregister(exprasmlist,p.location.registerhigh);
  59. rg.ungetregister(exprasmlist,p.location.registerlow);
  60. end
  61. else
  62. begin
  63. cg.a_load_reg_ref(exprasmlist,OS_64,
  64. p.location.register,href);
  65. rg.ungetregister(exprasmlist,p.location.register);
  66. end;
  67. end
  68. else
  69. begin
  70. tg.gettempofsizereference(exprasmlist,4,href);
  71. p.temp_offset:=href.offset;
  72. cg.a_load_reg_ref(exprasmlist,OS_32,
  73. p.location.register,href);
  74. rg.ungetregister(exprasmlist,p.location.register);
  75. end;
  76. saved:=true;
  77. end
  78. else if (p.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) and
  79. ((p.location.reference.base<>R_NO) or
  80. (p.location.reference.index<>R_NO)
  81. ) then
  82. begin
  83. scratchreg := cg.get_scratch_reg(exprasmlist);
  84. cg.a_loadaddr_ref_reg(exprasmlist,p.location.reference,
  85. scratchreg);
  86. reference_release(exprasmlist,p.location.reference);
  87. tg.gettempofsizereference(exprasmlist,pointer_size,href);
  88. cg.a_load_reg_ref(exprasmlist,OS_ADDR,scratchreg,href);
  89. cg.free_scratch_reg(exprasmlist,scratchreg);
  90. p.temp_offset:=href.offset;
  91. saved:=true;
  92. end
  93. else saved:=false;
  94. end
  95. else saved:=false;
  96. maybe_savetotemp:=saved;
  97. end;
  98. procedure restorefromtemp(p : tnode;isint64 : boolean);
  99. var
  100. hregister : tregister;
  101. href : treference;
  102. begin
  103. hregister:=rg.getregisterint(exprasmlist);
  104. reset_reference(href);
  105. href.base:=procinfo^.framepointer;
  106. href.offset:=p.temp_offset;
  107. if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  108. begin
  109. p.location.registerlow:=hregister;
  110. if isint64 then
  111. begin
  112. if sizeof(aword) < 8 then
  113. begin
  114. p.location.registerhigh:=rg.getregisterint(exprasmlist);
  115. tcg64f32(cg).a_load64_ref_reg(exprasmlist,
  116. href,p.location.registerlow,p.location.registerhigh);
  117. end
  118. else
  119. cg.a_load_ref_reg(exprasmlist,OS_64,href,
  120. p.location.register);
  121. end
  122. else
  123. cg.a_load_ref_reg(exprasmlist,OS_32,href,p.location.register);
  124. end
  125. else
  126. begin
  127. reset_reference(p.location.reference);
  128. p.location.reference.base:=hregister;
  129. { Why is this done? We can never be sure about p^.left
  130. because otherwise secondload fails PM
  131. set_location(p^.left^.location,p^.location);}
  132. end;
  133. tg.ungetiftemp(exprasmlist,href);
  134. end;
  135. {$endif TEMPS_NOT_PUSH}
  136. procedure maketojumpbool(p : tnode; loadregvars: tloadregvars);
  137. {
  138. produces jumps to true respectively false labels using boolean expressions
  139. depending on whether the loading of regvars is currently being
  140. synchronized manually (such as in an if-node) or automatically (most of
  141. the other cases where this procedure is called), loadregvars can be
  142. "lr_load_regvars" or "lr_dont_load_regvars"
  143. }
  144. var
  145. opsize : tcgsize;
  146. storepos : tfileposinfo;
  147. begin
  148. if nf_error in p.flags then
  149. exit;
  150. storepos:=aktfilepos;
  151. aktfilepos:=p.fileinfo;
  152. if is_boolean(p.resulttype.def) then
  153. begin
  154. if loadregvars = lr_load_regvars then
  155. load_all_regvars(exprasmlist);
  156. if is_constboolnode(p) then
  157. begin
  158. if tordconstnode(p).value<>0 then
  159. cg.a_jmp_cond(exprasmlist,OC_NONE,truelabel)
  160. else
  161. cg.a_jmp_cond(exprasmlist,OC_NONE,falselabel)
  162. end
  163. else
  164. begin
  165. opsize:=def_cgsize(p.resulttype.def);
  166. case p.location.loc of
  167. LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
  168. begin
  169. if (p.location.loc = LOC_CREGISTER) then
  170. load_regvar_reg(exprasmlist,p.location.register);
  171. cg.a_cmp_const_loc_label(exprasmlist,opsize,OC_NE,
  172. 0,p.location,truelabel);
  173. { !!! should happen right after cmp (JM) }
  174. location_release(exprasmlist,p.location);
  175. cg.a_jmp_cond(exprasmlist,OC_NONE,falselabel);
  176. end;
  177. LOC_FLAGS :
  178. begin
  179. cg.a_jmp_flags(exprasmlist,p.location.resflags,
  180. truelabel);
  181. cg.a_jmp_cond(exprasmlist,OC_None,falselabel);
  182. end;
  183. end;
  184. end;
  185. end
  186. else
  187. internalerror(200112305);
  188. aktfilepos:=storepos;
  189. end;
  190. end.
  191. {
  192. $Log$
  193. Revision 1.7 2002-04-15 18:58:47 carl
  194. + target_info.size_of_pointer -> pointer_Size
  195. Revision 1.6 2002/04/06 18:10:42 jonas
  196. * several powerpc-related additions and fixes
  197. Revision 1.5 2002/04/04 19:05:57 peter
  198. * removed unused units
  199. * use tlocation.size in cg.a_*loc*() routines
  200. Revision 1.4 2002/04/02 17:11:28 peter
  201. * tlocation,treference update
  202. * LOC_CONSTANT added for better constant handling
  203. * secondadd splitted in multiple routines
  204. * location_force_reg added for loading a location to a register
  205. of a specified size
  206. * secondassignment parses now first the right and then the left node
  207. (this is compatible with Kylix). This saves a lot of push/pop especially
  208. with string operations
  209. * adapted some routines to use the new cg methods
  210. Revision 1.3 2002/03/31 20:26:34 jonas
  211. + a_loadfpu_* and a_loadmm_* methods in tcg
  212. * register allocation is now handled by a class and is mostly processor
  213. independent (+rgobj.pas and i386/rgcpu.pas)
  214. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  215. * some small improvements and fixes to the optimizer
  216. * some register allocation fixes
  217. * some fpuvaroffset fixes in the unary minus node
  218. * push/popusedregisters is now called rg.save/restoreusedregisters and
  219. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  220. also better optimizable)
  221. * fixed and optimized register saving/restoring for new/dispose nodes
  222. * LOC_FPU locations now also require their "register" field to be set to
  223. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  224. - list field removed of the tnode class because it's not used currently
  225. and can cause hard-to-find bugs
  226. Revision 1.2 2002/03/04 19:10:11 peter
  227. * removed compiler warnings
  228. Revision 1.1 2001/12/30 17:24:48 jonas
  229. * range checking is now processor independent (part in cgobj,
  230. part in cg64f32) and should work correctly again (it needed
  231. some changes after the changes of the low and high of
  232. tordef's to int64)
  233. * maketojumpbool() is now processor independent (in ncgutil)
  234. * getregister32 is now called getregisterint
  235. }