cpupara.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. {
  2. $Id$
  3. Copyright (c) 2002 by Florian Klaempfl
  4. Generates the argument location information for i386
  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 bymethodpointer
  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. { Generates the argument location information for i386.
  19. }
  20. unit cpupara;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. aasmtai,
  25. cpubase,
  26. globtype,
  27. cginfo,
  28. symconst,symtype,symdef,paramgr;
  29. type
  30. { Returns the location for the nr-st 32 Bit int parameter
  31. if every parameter before is an 32 Bit int parameter as well
  32. and if the calling conventions for the helper routines of the
  33. rtl are used.
  34. }
  35. ti386paramanager = class(tparamanager)
  36. function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
  37. function push_addr_param(def : tdef;calloption : tproccalloption) : boolean;override;
  38. function get_volatile_registers_int(calloption : tproccalloption):tsuperregisterset;override;
  39. function get_volatile_registers_fpu(calloption : tproccalloption):tsuperregisterset;override;
  40. function getintparaloc(list: taasmoutput; nr : longint) : tparalocation;override;
  41. procedure freeintparaloc(list: taasmoutput; nr : longint); override;
  42. function getparaloc(p : tdef) : tcgloc;
  43. procedure create_paraloc_info(p : tabstractprocdef; side: tcallercallee);override;
  44. function getselflocation(p : tabstractprocdef) : tparalocation;override;
  45. end;
  46. implementation
  47. uses
  48. systems,verbose,
  49. symsym,
  50. cpuinfo,
  51. cgbase;
  52. {****************************************************************************
  53. TI386PARAMANAGER
  54. ****************************************************************************}
  55. function ti386paramanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
  56. begin
  57. case target_info.system of
  58. system_i386_win32 :
  59. begin
  60. { Win32 returns small records in the FUNCTION_RETURN_REG }
  61. case def.deftype of
  62. recorddef :
  63. begin
  64. if (calloption in [pocall_stdcall,pocall_cdecl,pocall_cppdecl]) and (def.size<=8) then
  65. begin
  66. result:=false;
  67. exit;
  68. end;
  69. end;
  70. end;
  71. end;
  72. end;
  73. result:=inherited ret_in_param(def,calloption);
  74. end;
  75. function ti386paramanager.push_addr_param(def : tdef;calloption : tproccalloption) : boolean;
  76. begin
  77. case target_info.system of
  78. system_i386_win32 :
  79. begin
  80. case def.deftype of
  81. recorddef :
  82. begin
  83. if (calloption=pocall_stdcall) and (def.size<=8) then
  84. begin
  85. result:=false;
  86. exit;
  87. end;
  88. end;
  89. arraydef :
  90. begin
  91. if (tarraydef(def).highrange>=tarraydef(def).lowrange) and
  92. (calloption in [pocall_cdecl,pocall_cppdecl]) then
  93. begin
  94. result:=true;
  95. exit;
  96. end;
  97. end;
  98. end;
  99. end;
  100. end;
  101. result:=inherited push_addr_param(def,calloption);
  102. end;
  103. function ti386paramanager.get_volatile_registers_int(calloption : tproccalloption):tsuperregisterset;
  104. begin
  105. case calloption of
  106. pocall_internproc :
  107. result:=[];
  108. pocall_compilerproc :
  109. begin
  110. if pocall_default=pocall_oldfpccall then
  111. result:=[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI,RS_EBX]
  112. else
  113. result:=[RS_EAX,RS_EDX,RS_ECX];
  114. end;
  115. pocall_inline,
  116. pocall_register,
  117. pocall_safecall,
  118. pocall_stdcall,
  119. pocall_cdecl,
  120. pocall_cppdecl :
  121. result:=[RS_EAX,RS_EDX,RS_ECX];
  122. pocall_far16,
  123. pocall_pascal,
  124. pocall_oldfpccall :
  125. result:=[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI,RS_EBX];
  126. else
  127. internalerror(200309071);
  128. end;
  129. end;
  130. function ti386paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tsuperregisterset;
  131. begin
  132. result:=[first_fpu_supreg..last_fpu_supreg];;
  133. end;
  134. function ti386paramanager.getintparaloc(list: taasmoutput; nr : longint) : tparalocation;
  135. begin
  136. getintparaloc.loc:=LOC_REFERENCE;
  137. getintparaloc.reference.index:=NR_EBP;
  138. getintparaloc.reference.offset:=4*nr;
  139. end;
  140. procedure ti386paramanager.freeintparaloc(list: taasmoutput; nr : longint);
  141. begin
  142. { nothing to release }
  143. end;
  144. function ti386paramanager.getparaloc(p : tdef) : tcgloc;
  145. begin
  146. result:=LOC_REFERENCE;
  147. end;
  148. procedure ti386paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee);
  149. var
  150. hp : tparaitem;
  151. paraloc : tparalocation;
  152. begin
  153. hp:=tparaitem(p.para.first);
  154. while assigned(hp) do
  155. begin
  156. if hp.paratyp in [vs_var,vs_out] then
  157. paraloc.size:=OS_ADDR
  158. else
  159. paraloc.size:=def_cgsize(hp.paratype.def);
  160. paraloc.loc:=LOC_REFERENCE;
  161. if assigned(current_procinfo) then
  162. paraloc.reference.index:=current_procinfo.framepointer
  163. else
  164. paraloc.reference.index:=NR_FRAME_POINTER_REG;
  165. paraloc.reference.offset:=tvarsym(hp.parasym).adjusted_address;
  166. hp.paraloc[side]:=paraloc;
  167. {$warning callerparaloc shall not be the same as calleeparaloc}
  168. hp:=tparaitem(hp.next);
  169. end;
  170. { Function return }
  171. fillchar(paraloc,sizeof(tparalocation),0);
  172. paraloc.size:=def_cgsize(p.rettype.def);
  173. { Return in FPU register? }
  174. if p.rettype.def.deftype=floatdef then
  175. begin
  176. paraloc.loc:=LOC_FPUREGISTER;
  177. paraloc.register:=NR_FPU_RESULT_REG;
  178. end
  179. else
  180. { Return in register? }
  181. if not ret_in_param(p.rettype.def,p.proccalloption) then
  182. begin
  183. paraloc.loc:=LOC_REGISTER;
  184. {$ifndef cpu64bit}
  185. if paraloc.size in [OS_64,OS_S64] then
  186. begin
  187. paraloc.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
  188. paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
  189. end
  190. else
  191. {$endif cpu64bit}
  192. begin
  193. paraloc.register:=NR_FUNCTION_RETURN_REG;
  194. end;
  195. end
  196. else
  197. begin
  198. paraloc.loc:=LOC_REFERENCE;
  199. end;
  200. p.funcret_paraloc[side]:=paraloc;
  201. end;
  202. function ti386paramanager.getselflocation(p : tabstractprocdef) : tparalocation;
  203. var
  204. hsym : tvarsym;
  205. begin
  206. hsym:=tvarsym(trecorddef(methodpointertype.def).symtable.search('self'));
  207. if not assigned(hsym) then
  208. internalerror(200305251);
  209. getselflocation.loc:=LOC_REFERENCE;
  210. getselflocation.sp_fixup:=POINTER_SIZE;
  211. getselflocation.reference.index:=NR_STACK_POINTER_REG;
  212. getselflocation.reference.offset:=hsym.adjusted_address;
  213. end;
  214. begin
  215. paramanager:=ti386paramanager.create;
  216. end.
  217. {
  218. $Log$
  219. Revision 1.25 2003-09-08 18:28:51 peter
  220. * fix compilerproc for default=oldfpccall
  221. Revision 1.24 2003/09/07 22:09:35 peter
  222. * preparations for different default calling conventions
  223. * various RA fixes
  224. Revision 1.23 2003/09/03 15:55:01 peter
  225. * NEWRA branch merged
  226. Revision 1.22.2.2 2003/08/28 18:35:08 peter
  227. * tregister changed to cardinal
  228. Revision 1.22.2.1 2003/08/27 19:55:54 peter
  229. * first tregister patch
  230. Revision 1.22 2003/08/11 21:18:20 peter
  231. * start of sparc support for newra
  232. Revision 1.21 2003/07/05 20:11:41 jonas
  233. * create_paraloc_info() is now called separately for the caller and
  234. callee info
  235. * fixed ppc cycle
  236. Revision 1.20 2003/07/02 22:18:04 peter
  237. * paraloc splitted in callerparaloc,calleeparaloc
  238. * sparc calling convention updates
  239. Revision 1.19 2003/06/17 16:34:19 peter
  240. * freeintparaloc added
  241. Revision 1.18 2003/06/07 18:57:04 jonas
  242. + added freeintparaloc
  243. * ppc get/freeintparaloc now check whether the parameter regs are
  244. properly allocated/deallocated (and get an extra list para)
  245. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  246. * fixed lot of missing pi_do_call's
  247. Revision 1.17 2003/06/06 14:41:22 peter
  248. * needs cpuinfo
  249. Revision 1.16 2003/06/06 07:36:06 michael
  250. + Forgot a line in patch from peter
  251. Revision 1.15 2003/06/06 07:35:14 michael
  252. + Patch to Patch from peter
  253. Revision 1.14 2003/06/06 07:34:11 michael
  254. + Patch from peter
  255. Revision 1.13 2003/06/05 20:58:05 peter
  256. * updated
  257. Revision 1.12 2003/05/30 23:57:08 peter
  258. * more sparc cleanup
  259. * accumulator removed, splitted in function_return_reg (called) and
  260. function_result_reg (caller)
  261. Revision 1.11 2003/05/13 15:16:13 peter
  262. * removed ret_in_acc, it's the reverse of ret_in_param
  263. * fixed ret_in_param for win32 cdecl array
  264. Revision 1.10 2003/04/22 23:50:23 peter
  265. * firstpass uses expectloc
  266. * checks if there are differences between the expectloc and
  267. location.loc from secondpass in EXTDEBUG
  268. Revision 1.9 2003/04/22 14:33:38 peter
  269. * removed some notes/hints
  270. Revision 1.8 2003/01/08 18:43:57 daniel
  271. * Tregister changed into a record
  272. Revision 1.7 2002/12/24 15:56:50 peter
  273. * stackpointer_alloc added for adjusting ESP. Win32 needs
  274. this for the pageprotection
  275. Revision 1.6 2002/12/17 22:19:33 peter
  276. * fixed pushing of records>8 bytes with stdcall
  277. * simplified hightree loading
  278. Revision 1.5 2002/11/18 17:32:00 peter
  279. * pass proccalloption to ret_in_xxx and push_xxx functions
  280. Revision 1.4 2002/11/15 01:58:56 peter
  281. * merged changes from 1.0.7 up to 04-11
  282. - -V option for generating bug report tracing
  283. - more tracing for option parsing
  284. - errors for cdecl and high()
  285. - win32 import stabs
  286. - win32 records<=8 are returned in eax:edx (turned off by default)
  287. - heaptrc update
  288. - more info for temp management in .s file with EXTDEBUG
  289. Revision 1.3 2002/08/09 07:33:04 florian
  290. * a couple of interface related fixes
  291. Revision 1.2 2002/07/11 14:41:32 florian
  292. * start of the new generic parameter handling
  293. Revision 1.1 2002/07/07 09:52:33 florian
  294. * powerpc target fixed, very simple units can be compiled
  295. * some basic stuff for better callparanode handling, far from being finished
  296. }