cpupi.pas 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. This unit contains the CPU specific part of tprocinfo
  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. { This unit contains the CPU specific part of tprocinfo. }
  18. unit cpupi;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,cutils,
  23. procinfo,cpuinfo,psub,
  24. aasmdata;
  25. type
  26. tarmprocinfo = class(tcgprocinfo)
  27. { for arm thumb, we need to know the stackframe size before
  28. starting procedure compilation, so this contains the stack frame size, the compiler
  29. should assume
  30. if this size is too little the procedure must be compiled again with a larger value }
  31. stackframesize,
  32. floatregstart : aint;
  33. // procedure handle_body_start;override;
  34. // procedure after_pass1;override;
  35. procedure set_first_temp_offset;override;
  36. function calc_stackframe_size:longint;override;
  37. procedure init_framepointer; override;
  38. procedure generate_parameter_info;override;
  39. procedure allocate_got_register(list : TAsmList);override;
  40. end;
  41. implementation
  42. uses
  43. globals,systems,
  44. cpubase,
  45. tgobj,
  46. symconst,symtype,symsym,paramgr,
  47. cgbase,cgutils,
  48. cgobj,
  49. defutil;
  50. procedure tarmprocinfo.set_first_temp_offset;
  51. var
  52. localsize : aint;
  53. i : longint;
  54. begin
  55. { We allocate enough space to save all registers because we can't determine
  56. the necessary space because the used registers aren't known before
  57. secondpass is run. Even worse, patching
  58. the local offsets after generating the code could cause trouble because
  59. "shifter" constants could change to non-"shifter" constants. This
  60. is especially a problem when taking the address of a local. For now,
  61. this extra memory should hurt less than generating all local contants with offsets
  62. >256 as non shifter constants }
  63. if (po_nostackframe in procdef.procoptions) then
  64. begin
  65. { maxpushedparasize sghould be zero,
  66. if not we will get an error later. }
  67. tg.setfirsttemp(maxpushedparasize);
  68. exit;
  69. end;
  70. if tg.direction = -1 then
  71. begin
  72. if (target_info.system<>system_arm_darwin) then
  73. { Non-Darwin, worst case: r4-r10,r11,r13,r14,r15 is saved -> -28-16, but we
  74. always adjust the frame pointer to point to the first stored
  75. register (= last register in list above) -> + 4 }
  76. tg.setfirsttemp(-28-16)
  77. else
  78. { on Darwin first r4-r7,r14 are saved, then r7 is adjusted to
  79. point to the saved r7, and next r8,r10,r11 gets saved -> -24
  80. (r4-r6 and r8,r10,r11) }
  81. tg.setfirsttemp(-24)
  82. end
  83. else
  84. tg.setfirsttemp(maxpushedparasize);
  85. { estimate stack frame size }
  86. if current_settings.cputype in cpu_thumb then
  87. begin
  88. stackframesize:=maxpushedparasize+32;
  89. localsize:=0;
  90. for i:=0 to procdef.localst.SymList.Count-1 do
  91. if tsym(procdef.localst.SymList[i]).typ=localvarsym then
  92. inc(localsize,tabstractnormalvarsym(procdef.localst.SymList[i]).getsize);
  93. inc(stackframesize,localsize);
  94. localsize:=0;
  95. for i:=0 to procdef.parast.SymList.Count-1 do
  96. if tsym(procdef.parast.SymList[i]).typ=paravarsym then
  97. if is_open_string(tabstractnormalvarsym(procdef.parast.SymList[i]).vardef) then
  98. inc(localsize,256)
  99. else
  100. inc(localsize,tabstractnormalvarsym(procdef.parast.SymList[i]).getsize);
  101. inc(stackframesize,localsize);
  102. if pi_needs_implicit_finally in flags then
  103. inc(stackframesize,40);
  104. if pi_uses_exceptions in flags then
  105. inc(stackframesize,40);
  106. if procdef.proctypeoption in [potype_constructor] then
  107. inc(stackframesize,40*2);
  108. inc(stackframesize,estimatedtempsize);
  109. stackframesize:=Align(stackframesize,8);
  110. end;
  111. end;
  112. function tarmprocinfo.calc_stackframe_size:longint;
  113. var
  114. firstfloatreg,lastfloatreg,
  115. r : byte;
  116. floatsavesize : aword;
  117. regs: tcpuregisterset;
  118. begin
  119. if current_settings.cputype in cpu_thumb then
  120. result:=stackframesize
  121. else
  122. begin
  123. maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
  124. floatsavesize:=0;
  125. case current_settings.fputype of
  126. fpu_fpa,
  127. fpu_fpa10,
  128. fpu_fpa11:
  129. begin
  130. { save floating point registers? }
  131. firstfloatreg:=RS_NO;
  132. regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
  133. for r:=RS_F0 to RS_F7 do
  134. if r in regs then
  135. begin
  136. if firstfloatreg=RS_NO then
  137. firstfloatreg:=r;
  138. lastfloatreg:=r;
  139. end;
  140. if firstfloatreg<>RS_NO then
  141. floatsavesize:=(lastfloatreg-firstfloatreg+1)*12;
  142. end;
  143. fpu_vfpv2,
  144. fpu_vfpv3,
  145. fpu_vfpv3_d16:
  146. begin
  147. floatsavesize:=0;
  148. regs:=cg.rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
  149. for r:=RS_D0 to RS_D31 do
  150. if r in regs then
  151. inc(floatsavesize,8);
  152. end;
  153. fpu_fpv4_s16:
  154. begin
  155. floatsavesize:=0;
  156. regs:=cg.rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
  157. for r:=RS_D0 to RS_D15 do
  158. if r in regs then
  159. inc(floatsavesize,8);
  160. end;
  161. end;
  162. floatsavesize:=align(floatsavesize,max(current_settings.alignment.localalignmin,4));
  163. result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize+aint(floatsavesize);
  164. floatregstart:=tg.direction*result+maxpushedparasize;
  165. if tg.direction=1 then
  166. dec(floatregstart,floatsavesize);
  167. end;
  168. end;
  169. procedure tarmprocinfo.init_framepointer;
  170. begin
  171. if (target_info.system in systems_darwin) or (current_settings.cputype in cpu_thumb) then
  172. begin
  173. RS_FRAME_POINTER_REG:=RS_R7;
  174. NR_FRAME_POINTER_REG:=NR_R7;
  175. end
  176. else
  177. begin
  178. RS_FRAME_POINTER_REG:=RS_R11;
  179. NR_FRAME_POINTER_REG:=NR_R11;
  180. end;
  181. end;
  182. procedure tarmprocinfo.generate_parameter_info;
  183. begin
  184. procdef.total_stackframe_size:=stackframesize;
  185. inherited generate_parameter_info;
  186. end;
  187. procedure tarmprocinfo.allocate_got_register(list: TAsmList);
  188. begin
  189. { darwin doesn't use a got }
  190. if tf_pic_uses_got in target_info.flags then
  191. got := cg.getaddressregister(list);
  192. end;
  193. begin
  194. cprocinfo:=tarmprocinfo;
  195. end.