cpupi.pas 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. cutils,globtype,
  23. cpubase,
  24. cgbase,aasmdata,
  25. procinfo,cpuinfo,psub;
  26. type
  27. txtensaprocinfo = class(tcgprocinfo)
  28. callins,callxins : TAsmOp;
  29. stackframesize,
  30. stackpaddingreg: TSuperRegister;
  31. needs_frame_pointer: boolean;
  32. { highest N used in a call instruction }
  33. maxcall : Byte;
  34. // procedure handle_body_start;override;
  35. // procedure after_pass1;override;
  36. constructor create(aparent: tprocinfo); override;
  37. procedure set_first_temp_offset;override;
  38. function calc_stackframe_size:longint;override;
  39. procedure init_framepointer;override;
  40. procedure generate_parameter_info;override;
  41. end;
  42. implementation
  43. uses
  44. globals,systems,
  45. verbose,
  46. tgobj,
  47. symconst,symtype,symsym,symcpu,symdef,
  48. paramgr,
  49. cgutils,
  50. cgobj,
  51. defutil,
  52. aasmcpu;
  53. constructor txtensaprocinfo.create(aparent: tprocinfo);
  54. begin
  55. inherited create(aparent);
  56. maxpushedparasize:=0;
  57. if target_info.abi=abi_xtensa_windowed then
  58. begin
  59. callins:=A_CALL8;
  60. callxins:=A_CALLX8;
  61. { set properly }
  62. maxcall:=8;
  63. { we do not use a frame pointer for the windowed abi }
  64. framepointer:=NR_STACK_POINTER_REG;
  65. end
  66. else
  67. begin
  68. callins:=A_CALL0;
  69. callxins:=A_CALLX0;
  70. maxcall:=0;
  71. { we do not use a frame pointer }
  72. framepointer:=NR_STACK_POINTER_REG;
  73. end;
  74. end;
  75. procedure txtensaprocinfo.set_first_temp_offset;
  76. var
  77. localsize : aint;
  78. i : longint;
  79. begin
  80. maxpushedparasize:=Align(maxpushedparasize,target_info.alignment.localalignmax);
  81. tg.setfirsttemp(maxpushedparasize);
  82. if po_nostackframe in procdef.procoptions then
  83. exit;
  84. { estimate stack frame size }
  85. if pi_estimatestacksize in flags then
  86. begin
  87. stackframesize:=align(maxpushedparasize,target_info.alignment.localalignmax);
  88. localsize:=0;
  89. for i:=0 to procdef.localst.SymList.Count-1 do
  90. if tsym(procdef.localst.SymList[i]).typ=localvarsym then
  91. begin
  92. localsize:=align(localsize,tabstractnormalvarsym(procdef.localst.SymList[i]).vardef.alignment);
  93. inc(localsize,tabstractnormalvarsym(procdef.localst.SymList[i]).getsize);
  94. end;
  95. inc(stackframesize,localsize);
  96. stackframesize:=align(stackframesize,target_info.alignment.localalignmax);
  97. localsize:=0;
  98. for i:=0 to procdef.parast.SymList.Count-1 do
  99. if tsym(procdef.parast.SymList[i]).typ=paravarsym then
  100. begin
  101. if tabstractnormalvarsym(procdef.parast.SymList[i]).varspez in [vs_var,vs_out,vs_constref] then
  102. begin
  103. localsize:=align(localsize,4);
  104. inc(localsize,4)
  105. end
  106. else if is_open_string(tabstractnormalvarsym(procdef.parast.SymList[i]).vardef) then
  107. inc(localsize,256)
  108. else
  109. begin
  110. localsize:=align(localsize,tparavarsym(procdef.parast.SymList[i]).paraloc[calleeside].alignment);
  111. { getsize returns 0 for e.g. open arrays, however, they require a pointer at the stack, so
  112. allocate one pointer }
  113. if tabstractnormalvarsym(procdef.parast.SymList[i]).getsize=0 then
  114. inc(localsize,voidpointertype.size)
  115. else
  116. inc(localsize,tabstractnormalvarsym(procdef.parast.SymList[i]).getsize);
  117. end;
  118. end;
  119. inc(stackframesize,localsize);
  120. stackframesize:=align(stackframesize,target_info.alignment.localalignmax);
  121. inc(stackframesize,estimatedtempsize);
  122. stackframesize:=align(stackframesize,4);
  123. if pi_needs_implicit_finally in flags then
  124. inc(stackframesize,40);
  125. if pi_uses_exceptions in flags then
  126. inc(stackframesize,40);
  127. if procdef.proctypeoption in [potype_constructor] then
  128. inc(stackframesize,40*2);
  129. { default spill area }
  130. inc(stackframesize,4*4);
  131. { additional spill area? }
  132. if pi_do_call in current_procinfo.flags then
  133. inc(stackframesize,maxcall*4);
  134. stackframesize:=Align(stackframesize,target_info.alignment.localalignmax);
  135. end;
  136. end;
  137. function txtensaprocinfo.calc_stackframe_size:longint;
  138. var
  139. r, extra: byte;
  140. regs: tcpuregisterset;
  141. begin
  142. if pi_estimatestacksize in flags then
  143. begin
  144. if pi_do_call in current_procinfo.flags then
  145. extra:=maxcall*4+4*4
  146. else
  147. extra:=4*4;
  148. if Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+extra>stackframesize then
  149. InternalError(2020082801);
  150. result:=stackframesize
  151. end
  152. else
  153. result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize;
  154. end;
  155. procedure txtensaprocinfo.generate_parameter_info;
  156. begin
  157. tcpuprocdef(procdef).total_stackframe_size:=stackframesize;
  158. inherited generate_parameter_info;
  159. end;
  160. procedure txtensaprocinfo.init_framepointer;
  161. begin
  162. if target_info.abi=abi_xtensa_call0 then
  163. begin
  164. RS_FRAME_POINTER_REG:=RS_A15;
  165. NR_FRAME_POINTER_REG:=NR_A15;
  166. end
  167. else
  168. begin
  169. { a frame pointer would be only needed if we do an "alloca" }
  170. RS_FRAME_POINTER_REG:=RS_A15;
  171. NR_FRAME_POINTER_REG:=NR_A15;
  172. end;
  173. end;
  174. begin
  175. cprocinfo:=txtensaprocinfo;
  176. end.