cpupara.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. {*****************************************************************************}
  2. { File : cpupara.pas }
  3. { Author : Mazen NEIFER }
  4. { Project : Free Pascal Compiler (FPC) }
  5. { Creation date : 2002\07\13 }
  6. { Last modification date : 2002\08\20 }
  7. { Licence : GPL }
  8. { Bug report : [email protected] }
  9. {*****************************************************************************}
  10. {
  11. $Id$
  12. Copyright (c) 2002 by Florian Klaempfl
  13. PowerPC specific calling conventions
  14. This program is free software; you can redistribute it and/or modify
  15. it under the terms of the GNU General Public License as published by
  16. the Free Software Foundation; either version 2 of the License, or
  17. (at your option) any later version.
  18. This program is distributed in the hope that it will be useful,
  19. but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. GNU General Public License for more details.
  22. You should have received a copy of the GNU General Public License
  23. along with this program; if not, write to the Free Software
  24. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. ****************************************************************************}
  26. unit cpupara;
  27. {SPARC specific calling conventions are handled by this unit}
  28. {$INCLUDE fpcdefs.inc}
  29. interface
  30. uses
  31. cpubase,
  32. symconst,symbase,symtype,symdef,paramgr;
  33. type
  34. tSparcparamanager = class(tparamanager)
  35. function getintparaloc(nr : longint) : tparalocation;override;
  36. procedure create_param_loc_info(p : tabstractprocdef);override;
  37. function getfuncretparaloc(p : tabstractprocdef) : tparalocation;override;
  38. end;
  39. implementation
  40. uses
  41. verbose,
  42. globtype,
  43. cpuinfo,cginfo,cgbase,
  44. defbase;
  45. function tSparcparamanager.getintparaloc(nr : longint) : tparalocation;
  46. begin
  47. fillchar(result,sizeof(tparalocation),0);
  48. if nr<1 then
  49. internalerror(2002070801)
  50. else if nr<=8 then
  51. begin
  52. result.loc:=LOC_REGISTER;
  53. result.register:=tregister(longint(R_O0)+nr);
  54. end
  55. else
  56. begin
  57. result.loc:=LOC_REFERENCE;
  58. result.reference.index:=stack_pointer_reg;
  59. result.reference.offset:=(nr-8)*4;
  60. end;
  61. end;
  62. function getparaloc(p : tdef) : tloc;
  63. begin
  64. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  65. if push_addr_param for the def is true
  66. }
  67. case p.deftype of
  68. orddef:
  69. getparaloc:=LOC_REGISTER;
  70. floatdef:
  71. getparaloc:=LOC_FPUREGISTER;
  72. enumdef:
  73. getparaloc:=LOC_REGISTER;
  74. pointerdef:
  75. getparaloc:=LOC_REGISTER;
  76. formaldef:
  77. getparaloc:=LOC_REGISTER;
  78. classrefdef:
  79. getparaloc:=LOC_REGISTER;
  80. recorddef:
  81. getparaloc:=LOC_REFERENCE;
  82. objectdef:
  83. if is_object(p) then
  84. getparaloc:=LOC_REFERENCE
  85. else
  86. getparaloc:=LOC_REGISTER;
  87. stringdef:
  88. if is_shortstring(p) or is_longstring(p) then
  89. getparaloc:=LOC_REFERENCE
  90. else
  91. getparaloc:=LOC_REGISTER;
  92. procvardef:
  93. if (po_methodpointer in tprocvardef(p).procoptions) then
  94. getparaloc:=LOC_REFERENCE
  95. else
  96. getparaloc:=LOC_REGISTER;
  97. filedef:
  98. getparaloc:=LOC_REGISTER;
  99. arraydef:
  100. getparaloc:=LOC_REFERENCE;
  101. setdef:
  102. if is_smallset(p) then
  103. getparaloc:=LOC_REGISTER
  104. else
  105. getparaloc:=LOC_REFERENCE;
  106. variantdef:
  107. getparaloc:=LOC_REFERENCE;
  108. { avoid problems with errornous definitions }
  109. errordef:
  110. getparaloc:=LOC_REGISTER;
  111. else
  112. internalerror(2002071001);
  113. end;
  114. end;
  115. procedure tSparcparamanager.create_param_loc_info(p : tabstractprocdef);
  116. var
  117. nextintreg,nextfloatreg,nextmmreg : tregister;
  118. stack_offset : aword;
  119. hp : tparaitem;
  120. loc : tloc;
  121. is_64bit: boolean;
  122. begin
  123. nextintreg:=R_O3;
  124. nextfloatreg:=R_F1;
  125. nextmmreg:=R_NONE;
  126. stack_offset:=0;
  127. { pointer for structured results ? }
  128. if not is_void(p.rettype.def) then
  129. begin
  130. if not(ret_in_reg(p.rettype.def)) then
  131. inc(nextintreg);
  132. end;
  133. { frame pointer for nested procedures? }
  134. { inc(nextintreg); }
  135. { constructor? }
  136. { destructor? }
  137. hp:=tparaitem(p.para.last);
  138. while assigned(hp) do
  139. begin
  140. loc:=getparaloc(hp.paratype.def);
  141. hp.paraloc.sp_fixup:=0;
  142. case loc of
  143. LOC_REGISTER:
  144. begin
  145. hp.paraloc.size := def_cgsize(hp.paratype.def);
  146. { for things like formaldef }
  147. if hp.paraloc.size = OS_NO then
  148. hp.paraloc.size := OS_ADDR;
  149. is_64bit := hp.paraloc.size in [OS_64,OS_S64];
  150. if nextintreg<=tregister(ord(R_O4)-ord(is_64bit)) then
  151. begin
  152. hp.paraloc.loc:=LOC_REGISTER;
  153. hp.paraloc.registerlow:=nextintreg;
  154. inc(nextintreg);
  155. if is_64bit then
  156. begin
  157. hp.paraloc.registerhigh:=nextintreg;
  158. inc(nextintreg);
  159. end;
  160. end
  161. else
  162. begin
  163. nextintreg := R_O5;
  164. hp.paraloc.loc:=LOC_REFERENCE;
  165. hp.paraloc.reference.index:=stack_pointer_reg;
  166. hp.paraloc.reference.offset:=stack_offset;
  167. if not is_64bit then
  168. inc(stack_offset,4)
  169. else
  170. inc(stack_offset,8);
  171. end;
  172. end;
  173. LOC_FPUREGISTER:
  174. begin
  175. if hp.paratyp in [vs_var,vs_out] then
  176. begin
  177. if nextintreg<=R_O5 then
  178. begin
  179. hp.paraloc.size:=OS_ADDR;
  180. hp.paraloc.loc:=LOC_REGISTER;
  181. hp.paraloc.register:=nextintreg;
  182. inc(nextintreg);
  183. end
  184. else
  185. begin
  186. {!!!!!!!}
  187. hp.paraloc.size:=def_cgsize(hp.paratype.def);
  188. internalerror(2002071006);
  189. end;
  190. end
  191. else if nextfloatreg<=R_F10 then
  192. begin
  193. hp.paraloc.size:=def_cgsize(hp.paratype.def);
  194. hp.paraloc.loc:=LOC_FPUREGISTER;
  195. hp.paraloc.register:=nextfloatreg;
  196. inc(nextfloatreg);
  197. end
  198. else
  199. begin
  200. {!!!!!!!}
  201. hp.paraloc.size:=def_cgsize(hp.paratype.def);
  202. internalerror(2002071004);
  203. end;
  204. end;
  205. LOC_REFERENCE:
  206. begin
  207. hp.paraloc.size:=OS_ADDR;
  208. if push_addr_param(hp.paratype.def,p.proccalloption in [pocall_cdecl,pocall_cppdecl]) or (hp.paratyp in [vs_var,vs_out]) then
  209. begin
  210. if nextintreg<=R_O5 then
  211. begin
  212. hp.paraloc.loc:=LOC_REGISTER;
  213. hp.paraloc.register:=nextintreg;
  214. inc(nextintreg);
  215. end
  216. else
  217. begin
  218. hp.paraloc.loc:=LOC_REFERENCE;
  219. hp.paraloc.reference.index:=stack_pointer_reg;
  220. hp.paraloc.reference.offset:=stack_offset;
  221. inc(stack_offset,4);
  222. end;
  223. end
  224. else
  225. begin
  226. hp.paraloc.loc:=LOC_REFERENCE;
  227. hp.paraloc.reference.index:=stack_pointer_reg;
  228. hp.paraloc.reference.offset:=stack_offset;
  229. inc(stack_offset,hp.paratype.def.size);
  230. end;
  231. end;
  232. else
  233. internalerror(2002071002);
  234. end;
  235. hp:=tparaitem(hp.previous);
  236. end;
  237. end;
  238. function tSparcparamanager.getfuncretparaloc(p : tabstractprocdef) : tparalocation;
  239. begin
  240. case p.rettype.def.deftype of
  241. orddef,
  242. enumdef:
  243. begin
  244. getfuncretparaloc.loc:=LOC_REGISTER;
  245. getfuncretparaloc.register:=R_O0;
  246. getfuncretparaloc.size:=def_cgsize(p.rettype.def);
  247. if getfuncretparaloc.size in [OS_S64,OS_64] then
  248. getfuncretparaloc.registerhigh:=R_O1;
  249. end;
  250. floatdef:
  251. begin
  252. getfuncretparaloc.loc:=LOC_FPUREGISTER;
  253. getfuncretparaloc.register:=R_F1;
  254. getfuncretparaloc.size:=def_cgsize(p.rettype.def);
  255. end;
  256. { smallsets are OS_INT in R3, others are OS_ADDR in R3 -> the same }
  257. { ugly, I know :) (JM) }
  258. setdef,
  259. variantdef,
  260. pointerdef,
  261. formaldef,
  262. classrefdef,
  263. recorddef,
  264. objectdef,
  265. stringdef,
  266. procvardef,
  267. filedef,
  268. arraydef,
  269. errordef:
  270. begin
  271. getfuncretparaloc.loc:=LOC_REGISTER;
  272. getfuncretparaloc.register:=R_O0;
  273. getfuncretparaloc.size:=OS_ADDR;
  274. end;
  275. else
  276. internalerror(2002090903);
  277. end;
  278. end;
  279. BEGIN
  280. paramanager:=TSparcParaManager.create;
  281. end.
  282. {
  283. $Log$
  284. Revision 1.2 2002-10-04 21:57:42 mazen
  285. * register allocation for parameters now done in cpupara, but InternalError(200109223) in cgcpu.pas:1053 is still not fixed du to location_force problem in ncgutils.pas:419
  286. Revision 1.1 2002/08/21 13:30:07 mazen
  287. *** empty log message ***
  288. Revision 1.2 2002/07/11 14:41:34 florian
  289. * start of the new generic parameter handling
  290. Revision 1.1 2002/07/07 09:44:32 florian
  291. * powerpc target fixed, very simple units can be compiled
  292. }