cpupara.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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. with Result do
  49. if nr<1
  50. then
  51. InternalError(2002070801)
  52. else if nr<=8
  53. then
  54. begin
  55. loc:=LOC_REGISTER;
  56. register:=tregister(longint(R_O0)+nr);
  57. end
  58. else
  59. begin
  60. loc:=LOC_REFERENCE;
  61. reference.index:=stack_pointer_reg;
  62. reference.offset:=(nr-8)*4;
  63. end;
  64. end;
  65. function getparaloc(p : tdef) : tloc;
  66. begin
  67. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  68. if push_addr_param for the def is true
  69. }
  70. case p.deftype of
  71. orddef:
  72. getparaloc:=LOC_REGISTER;
  73. floatdef:
  74. getparaloc:=LOC_FPUREGISTER;
  75. enumdef:
  76. getparaloc:=LOC_REGISTER;
  77. pointerdef:
  78. getparaloc:=LOC_REGISTER;
  79. formaldef:
  80. getparaloc:=LOC_REGISTER;
  81. classrefdef:
  82. getparaloc:=LOC_REGISTER;
  83. recorddef:
  84. getparaloc:=LOC_REFERENCE;
  85. objectdef:
  86. if is_object(p) then
  87. getparaloc:=LOC_REFERENCE
  88. else
  89. getparaloc:=LOC_REGISTER;
  90. stringdef:
  91. if is_shortstring(p) or is_longstring(p) then
  92. getparaloc:=LOC_REFERENCE
  93. else
  94. getparaloc:=LOC_REGISTER;
  95. procvardef:
  96. if (po_methodpointer in tprocvardef(p).procoptions) then
  97. getparaloc:=LOC_REFERENCE
  98. else
  99. getparaloc:=LOC_REGISTER;
  100. filedef:
  101. getparaloc:=LOC_REGISTER;
  102. arraydef:
  103. getparaloc:=LOC_REFERENCE;
  104. setdef:
  105. if is_smallset(p) then
  106. getparaloc:=LOC_REGISTER
  107. else
  108. getparaloc:=LOC_REFERENCE;
  109. variantdef:
  110. getparaloc:=LOC_REFERENCE;
  111. { avoid problems with errornous definitions }
  112. errordef:
  113. getparaloc:=LOC_REGISTER;
  114. else
  115. internalerror(2002071001);
  116. end;
  117. end;
  118. procedure tSparcparamanager.create_param_loc_info(p : tabstractprocdef);
  119. var
  120. nextintreg,nextfloatreg,nextmmreg : tregister;
  121. stack_offset : aword;
  122. hp : tparaitem;
  123. loc : tloc;
  124. is_64bit: boolean;
  125. begin
  126. nextintreg:=R_O3;
  127. nextfloatreg:=R_F1;
  128. nextmmreg:=R_NONE;
  129. stack_offset:=0;
  130. { pointer for structured results ? }
  131. if not is_void(p.rettype.def) then
  132. begin
  133. if not(ret_in_reg(p.rettype.def)) then
  134. inc(nextintreg);
  135. end;
  136. { frame pointer for nested procedures? }
  137. { inc(nextintreg); }
  138. { constructor? }
  139. { destructor? }
  140. hp:=tparaitem(p.para.last);
  141. while assigned(hp) do
  142. begin
  143. loc:=getparaloc(hp.paratype.def);
  144. hp.paraloc.sp_fixup:=0;
  145. case loc of
  146. LOC_REGISTER:
  147. begin
  148. hp.paraloc.size := def_cgsize(hp.paratype.def);
  149. { for things like formaldef }
  150. if hp.paraloc.size = OS_NO then
  151. hp.paraloc.size := OS_ADDR;
  152. is_64bit := hp.paraloc.size in [OS_64,OS_S64];
  153. if nextintreg<=tregister(ord(R_O4)-ord(is_64bit)) then
  154. begin
  155. hp.paraloc.loc:=LOC_REGISTER;
  156. hp.paraloc.registerlow:=nextintreg;
  157. inc(nextintreg);
  158. if is_64bit then
  159. begin
  160. hp.paraloc.registerhigh:=nextintreg;
  161. inc(nextintreg);
  162. end;
  163. end
  164. else
  165. begin
  166. nextintreg := R_O5;
  167. hp.paraloc.loc:=LOC_REFERENCE;
  168. hp.paraloc.reference.index:=stack_pointer_reg;
  169. hp.paraloc.reference.offset:=stack_offset;
  170. if not is_64bit then
  171. inc(stack_offset,4)
  172. else
  173. inc(stack_offset,8);
  174. end;
  175. end;
  176. LOC_FPUREGISTER:
  177. begin
  178. if hp.paratyp in [vs_var,vs_out] then
  179. begin
  180. if nextintreg<=R_O5 then
  181. begin
  182. hp.paraloc.size:=OS_ADDR;
  183. hp.paraloc.loc:=LOC_REGISTER;
  184. hp.paraloc.register:=nextintreg;
  185. inc(nextintreg);
  186. end
  187. else
  188. begin
  189. {!!!!!!!}
  190. hp.paraloc.size:=def_cgsize(hp.paratype.def);
  191. internalerror(2002071006);
  192. end;
  193. end
  194. else if nextfloatreg<=R_F10 then
  195. begin
  196. hp.paraloc.size:=def_cgsize(hp.paratype.def);
  197. hp.paraloc.loc:=LOC_FPUREGISTER;
  198. hp.paraloc.register:=nextfloatreg;
  199. inc(nextfloatreg);
  200. end
  201. else
  202. begin
  203. {!!!!!!!}
  204. hp.paraloc.size:=def_cgsize(hp.paratype.def);
  205. internalerror(2002071004);
  206. end;
  207. end;
  208. LOC_REFERENCE:
  209. begin
  210. hp.paraloc.size:=OS_ADDR;
  211. if push_addr_param(hp.paratype.def,p.proccalloption in [pocall_cdecl,pocall_cppdecl]) or (hp.paratyp in [vs_var,vs_out]) then
  212. begin
  213. if nextintreg<=R_O5 then
  214. begin
  215. hp.paraloc.loc:=LOC_REGISTER;
  216. hp.paraloc.register:=nextintreg;
  217. inc(nextintreg);
  218. end
  219. else
  220. begin
  221. hp.paraloc.loc:=LOC_REFERENCE;
  222. hp.paraloc.reference.index:=stack_pointer_reg;
  223. hp.paraloc.reference.offset:=stack_offset;
  224. inc(stack_offset,4);
  225. end;
  226. end
  227. else
  228. begin
  229. hp.paraloc.loc:=LOC_REFERENCE;
  230. hp.paraloc.reference.index:=stack_pointer_reg;
  231. hp.paraloc.reference.offset:=stack_offset;
  232. inc(stack_offset,hp.paratype.def.size);
  233. end;
  234. end;
  235. else
  236. internalerror(2002071002);
  237. end;
  238. hp:=tparaitem(hp.previous);
  239. end;
  240. end;
  241. function tSparcparamanager.getfuncretparaloc(p : tabstractprocdef) : tparalocation;
  242. begin
  243. case p.rettype.def.deftype of
  244. orddef,
  245. enumdef:
  246. begin
  247. getfuncretparaloc.loc:=LOC_REGISTER;
  248. getfuncretparaloc.register:=R_O0;
  249. getfuncretparaloc.size:=def_cgsize(p.rettype.def);
  250. if getfuncretparaloc.size in [OS_S64,OS_64] then
  251. getfuncretparaloc.registerhigh:=R_O1;
  252. end;
  253. floatdef:
  254. begin
  255. getfuncretparaloc.loc:=LOC_FPUREGISTER;
  256. getfuncretparaloc.register:=R_F1;
  257. getfuncretparaloc.size:=def_cgsize(p.rettype.def);
  258. end;
  259. { smallsets are OS_INT in R3, others are OS_ADDR in R3 -> the same }
  260. { ugly, I know :) (JM) }
  261. setdef,
  262. variantdef,
  263. pointerdef,
  264. formaldef,
  265. classrefdef,
  266. recorddef,
  267. objectdef,
  268. stringdef,
  269. procvardef,
  270. filedef,
  271. arraydef,
  272. errordef:
  273. begin
  274. getfuncretparaloc.loc:=LOC_REGISTER;
  275. getfuncretparaloc.register:=R_O0;
  276. getfuncretparaloc.size:=OS_ADDR;
  277. end;
  278. else
  279. internalerror(2002090903);
  280. end;
  281. end;
  282. BEGIN
  283. paramanager:=TSparcParaManager.create;
  284. end.
  285. {
  286. $Log$
  287. Revision 1.3 2002-10-07 20:33:05 mazen
  288. word alignement modified in g_stack_frame
  289. Revision 1.2 2002/10/04 21:57:42 mazen
  290. * 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
  291. Revision 1.1 2002/08/21 13:30:07 mazen
  292. *** empty log message ***
  293. Revision 1.2 2002/07/11 14:41:34 florian
  294. * start of the new generic parameter handling
  295. Revision 1.1 2002/07/07 09:44:32 florian
  296. * powerpc target fixed, very simple units can be compiled
  297. }