cpupi.pas 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. type
  25. tarmprocinfo = class(tcgprocinfo)
  26. floatregstart : aint;
  27. // procedure handle_body_start;override;
  28. // procedure after_pass1;override;
  29. procedure set_first_temp_offset;override;
  30. function calc_stackframe_size:longint;override;
  31. procedure init_framepointer; override;
  32. end;
  33. implementation
  34. uses
  35. globals,systems,
  36. cpubase,
  37. tgobj,
  38. symconst,paramgr,
  39. cgbase,cgutils,
  40. cgobj;
  41. procedure tarmprocinfo.set_first_temp_offset;
  42. begin
  43. { We allocate enough space to save all registers because we can't determine
  44. the necessary space because the used registers aren't known before
  45. secondpass is run. Even worse, patching
  46. the local offsets after generating the code could cause trouble because
  47. "shifter" constants could change to non-"shifter" constants. This
  48. is especially a problem when taking the address of a local. For now,
  49. this extra memory should hurt less than generating all local contants with offsets
  50. >256 as non shifter constants }
  51. if (po_nostackframe in procdef.procoptions) then
  52. begin
  53. { maxpushedparasize sghould be zero,
  54. if not we will get an error later. }
  55. tg.setfirsttemp(maxpushedparasize);
  56. exit;
  57. end;
  58. if tg.direction = -1 then
  59. begin
  60. if (target_info.system<>system_arm_darwin) then
  61. { Non-Darwin, worst case: r4-r10,r11,r13,r14,r15 is saved -> -28-16, but we
  62. always adjust the frame pointer to point to the first stored
  63. register (= last register in list above) -> + 4 }
  64. tg.setfirsttemp(-28-16)
  65. else
  66. { on Darwin first r4-r7,r14 are saved, then r7 is adjusted to
  67. point to the saved r7, and next r8,r10,r11 gets saved -> -24
  68. (r4-r6 and r8,r10,r11) }
  69. tg.setfirsttemp(-24)
  70. end
  71. else
  72. tg.setfirsttemp(maxpushedparasize);
  73. end;
  74. function tarmprocinfo.calc_stackframe_size:longint;
  75. var
  76. firstfloatreg,lastfloatreg,
  77. r : byte;
  78. floatsavesize : aword;
  79. regs: tcpuregisterset;
  80. begin
  81. maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
  82. floatsavesize:=0;
  83. case current_settings.fputype of
  84. fpu_fpa,
  85. fpu_fpa10,
  86. fpu_fpa11:
  87. begin
  88. { save floating point registers? }
  89. firstfloatreg:=RS_NO;
  90. regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
  91. for r:=RS_F0 to RS_F7 do
  92. if r in regs then
  93. begin
  94. if firstfloatreg=RS_NO then
  95. firstfloatreg:=r;
  96. lastfloatreg:=r;
  97. end;
  98. if firstfloatreg<>RS_NO then
  99. floatsavesize:=(lastfloatreg-firstfloatreg+1)*12;
  100. end;
  101. fpu_vfpv2,
  102. fpu_vfpv3,
  103. fpu_vfpv3_d16:
  104. begin
  105. floatsavesize:=0;
  106. regs:=cg.rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
  107. for r:=RS_D0 to RS_D31 do
  108. if r in regs then
  109. inc(floatsavesize,8);
  110. end;
  111. fpu_fpv4_s16:
  112. begin
  113. floatsavesize:=0;
  114. regs:=cg.rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
  115. for r:=RS_D0 to RS_D15 do
  116. if r in regs then
  117. inc(floatsavesize,8);
  118. end;
  119. end;
  120. floatsavesize:=align(floatsavesize,max(current_settings.alignment.localalignmin,4));
  121. result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize+aint(floatsavesize);
  122. floatregstart:=tg.direction*result+maxpushedparasize;
  123. if tg.direction=1 then
  124. dec(floatregstart,floatsavesize);
  125. end;
  126. procedure tarmprocinfo.init_framepointer;
  127. begin
  128. if (target_info.system in systems_darwin) or (current_settings.cputype in cpu_thumb) then
  129. begin
  130. RS_FRAME_POINTER_REG:=RS_R7;
  131. NR_FRAME_POINTER_REG:=NR_R7;
  132. end
  133. else
  134. begin
  135. RS_FRAME_POINTER_REG:=RS_R11;
  136. NR_FRAME_POINTER_REG:=NR_R11;
  137. end;
  138. end;
  139. begin
  140. cprocinfo:=tarmprocinfo;
  141. end.