cpupara.pas 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. Alpha specific calling conventions
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. { Alpha specific calling conventions are handled by this unit
  18. }
  19. unit cpupara;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. cpubase,
  24. symconst,symbase,symtype,symdef,paramgr;
  25. type
  26. tcpuparamanager = class(tparamanager)
  27. procedure create_param_loc_info(p : tabstractprocdef);override;
  28. function getfuncretparaloc(p : tabstractprocdef) : tparalocation;override;
  29. end;
  30. implementation
  31. uses
  32. verbose,
  33. globtype,
  34. cpuinfo,cginfo,cgbase,
  35. defbase;
  36. function getparaloc(p : tdef) : tloc;
  37. begin
  38. { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
  39. if push_addr_param for the def is true
  40. }
  41. case p.typ of
  42. orddef:
  43. getparaloc:=LOC_REGISTER;
  44. floatdef:
  45. getparaloc:=LOC_FPUREGISTER;
  46. enumdef:
  47. getparaloc:=LOC_REGISTER;
  48. pointerdef:
  49. getparaloc:=LOC_REGISTER;
  50. formaldef:
  51. getparaloc:=LOC_REGISTER;
  52. classrefdef:
  53. getparaloc:=LOC_REGISTER;
  54. recorddef:
  55. getparaloc:=LOC_REFERENCE;
  56. objectdef:
  57. if is_object(p) then
  58. getparaloc:=LOC_REFERENCE
  59. else
  60. getparaloc:=LOC_REGISTER;
  61. stringdef:
  62. if is_shortstring(p) or is_longstring(p) then
  63. getparaloc:=LOC_REFERENCE
  64. else
  65. getparaloc:=LOC_REGISTER;
  66. procvardef:
  67. if (po_methodpointer in tprocvardef(p).procoptions) then
  68. getparaloc:=LOC_REFERENCE
  69. else
  70. getparaloc:=LOC_REGISTER;
  71. filedef:
  72. getparaloc:=LOC_REGISTER;
  73. arraydef:
  74. getparaloc:=LOC_REFERENCE;
  75. setdef:
  76. if is_smallset(p) then
  77. getparaloc:=LOC_REGISTER
  78. else
  79. getparaloc:=LOC_REFERENCE;
  80. variantdef:
  81. getparaloc:=LOC_REFERENCE;
  82. { avoid problems with errornous definitions }
  83. errordef:
  84. getparaloc:=LOC_REGISTER;
  85. else
  86. internalerror(2002071001);
  87. end;
  88. end;
  89. procedure tcpuparamanager.create_param_loc_info(p : tabstractprocdef);
  90. var
  91. nextintreg,nextfloatreg,nextmmreg : tregister;
  92. stack_offset : aword;
  93. hp : tparaitem;
  94. loc : tloc;
  95. is_64bit: boolean;
  96. begin
  97. nextintreg:=R_3;
  98. nextfloatreg:=R_F1;
  99. // nextmmreg:=R_M1;
  100. stack_offset:=0;
  101. { pointer for structured results ? }
  102. if not is_void(p.returndef) then
  103. begin
  104. if not(ret_in_reg(p.returndef)) then
  105. inc(nextintreg);
  106. end;
  107. { frame pointer for nested procedures? }
  108. { inc(nextintreg); }
  109. { constructor? }
  110. { destructor? }
  111. hp:=tparaitem(p.para.last);
  112. while assigned(hp) do
  113. begin
  114. loc:=getparaloc(hp.paratype.def);
  115. hp.paraloc.sp_fixup:=0;
  116. case loc of
  117. LOC_REGISTER:
  118. begin
  119. hp.paraloc.size := def_cgsize(hp.paratype.def);
  120. { for things like formaldef }
  121. if hp.paraloc.size = OS_NO then
  122. hp.paraloc.size := OS_ADDR;
  123. is_64bit := hp.paraloc.size in [OS_64,OS_S64];
  124. if nextintreg<=tregister(ord(R_10)-ord(is_64bit)) then
  125. begin
  126. hp.paraloc.loc:=LOC_REGISTER;
  127. hp.paraloc.register64.reglo:=nextintreg;
  128. inc(nextintreg);
  129. if is_64bit then
  130. begin
  131. hp.paraloc.register64.reghi:=nextintreg;
  132. inc(nextintreg);
  133. end;
  134. end
  135. else
  136. begin
  137. nextintreg := R_11;
  138. hp.paraloc.loc:=LOC_REFERENCE;
  139. hp.paraloc.reference.index:=stack_pointer_reg;
  140. hp.paraloc.reference.offset:=stack_offset;
  141. if not is_64bit then
  142. inc(stack_offset,4)
  143. else
  144. inc(stack_offset,8);
  145. end;
  146. end;
  147. LOC_FPUREGISTER:
  148. begin
  149. if hp.paratyp in [vs_var,vs_out] then
  150. begin
  151. if nextintreg<=R_10 then
  152. begin
  153. hp.paraloc.size:=OS_ADDR;
  154. hp.paraloc.loc:=LOC_REGISTER;
  155. hp.paraloc.register:=nextintreg;
  156. inc(nextintreg);
  157. end
  158. else
  159. begin
  160. {!!!!!!!}
  161. hp.paraloc.size:=def_cgsize(hp.paratype.def);
  162. internalerror(2002071006);
  163. end;
  164. end
  165. else if nextfloatreg<=R_F10 then
  166. begin
  167. hp.paraloc.size:=def_cgsize(hp.paratype.def);
  168. hp.paraloc.loc:=LOC_FPUREGISTER;
  169. hp.paraloc.register:=nextfloatreg;
  170. inc(nextfloatreg);
  171. end
  172. else
  173. begin
  174. {!!!!!!!}
  175. hp.paraloc.size:=def_cgsize(hp.paratype.def);
  176. internalerror(2002071004);
  177. end;
  178. end;
  179. LOC_REFERENCE:
  180. begin
  181. hp.paraloc.size:=OS_ADDR;
  182. if push_addr_param(hp.paratype.def,p.proccalloption in [pocall_cdecl,pocall_cppdecl]) or (hp.paratyp in [vs_var,vs_out]) then
  183. begin
  184. if nextintreg<=R_10 then
  185. begin
  186. hp.paraloc.loc:=LOC_REGISTER;
  187. hp.paraloc.register:=nextintreg;
  188. inc(nextintreg);
  189. end
  190. else
  191. begin
  192. hp.paraloc.loc:=LOC_REFERENCE;
  193. hp.paraloc.reference.index:=stack_pointer_reg;
  194. hp.paraloc.reference.offset:=stack_offset;
  195. inc(stack_offset,4);
  196. end;
  197. end
  198. else
  199. begin
  200. hp.paraloc.loc:=LOC_REFERENCE;
  201. hp.paraloc.reference.index:=stack_pointer_reg;
  202. hp.paraloc.reference.offset:=stack_offset;
  203. inc(stack_offset,hp.paratype.def.size);
  204. end;
  205. end;
  206. else
  207. internalerror(2002071002);
  208. end;
  209. hp:=tparaitem(hp.previous);
  210. end;
  211. end;
  212. function tcpuparamanager.getfuncretparaloc(p : tabstractprocdef) : tparalocation;
  213. begin
  214. case p.returndef.typ of
  215. orddef,
  216. enumdef:
  217. begin
  218. getfuncretparaloc.loc:=LOC_REGISTER;
  219. getfuncretparaloc.register:=R_3;
  220. getfuncretparaloc.size:=def_cgsize(p.returndef);
  221. if getfuncretparaloc.size in [OS_S64,OS_64] then
  222. getfuncretparaloc.register64.reghi:=R_4;
  223. end;
  224. floatdef:
  225. begin
  226. getfuncretparaloc.loc:=LOC_FPUREGISTER;
  227. getfuncretparaloc.register:=R_F1;
  228. getfuncretparaloc.size:=def_cgsize(p.returndef);
  229. end;
  230. pointerdef,
  231. formaldef,
  232. classrefdef,
  233. recorddef,
  234. objectdef,
  235. stringdef,
  236. procvardef,
  237. filedef,
  238. arraydef,
  239. errordef:
  240. begin
  241. getfuncretparaloc.loc:=LOC_REGISTER;
  242. getfuncretparaloc.register:=R_3;
  243. getfuncretparaloc.size:=OS_ADDR;
  244. end;
  245. else
  246. internalerror(2002090903);
  247. end;
  248. end;
  249. begin
  250. paramanager:=tcpuparamanager.create;
  251. end.