cpupi.pas 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. {
  2. Copyright (c) 2002-2009 by Florian Klaempfl and David Zhang
  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. unit cpupi;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cutils,
  22. globtype,symdef,
  23. procinfo,cpuinfo,cpupara,
  24. psub,aasmdata,cgutils;
  25. type
  26. { tcpuprocinfo }
  27. tcpuprocinfo=class(tcgprocinfo)
  28. intregstart,
  29. floatregstart : aint;
  30. intregssave,
  31. floatregssave : byte;
  32. register_used : tparasupregsused;
  33. computed_local_size : longint;
  34. save_gp_ref: treference;
  35. //intparareg,
  36. //parasize : longint;
  37. constructor create(aparent:tprocinfo);override;
  38. function calc_stackframe_size:longint;override;
  39. procedure set_first_temp_offset;override;
  40. procedure allocate_got_register(list:tasmlist);override;
  41. procedure postprocess_code;override;
  42. end;
  43. { Used by Stabs debug info generator }
  44. function mips_extra_offset(procdef : tprocdef) : longint;
  45. implementation
  46. uses
  47. systems,globals,verbose,
  48. cpubase,cgbase,cgobj,
  49. tgobj,paramgr,symconst,symcpu,aasmcpu;
  50. constructor tcpuprocinfo.create(aparent: tprocinfo);
  51. begin
  52. inherited create(aparent);
  53. if (cs_generate_stackframes in current_settings.localswitches) or
  54. not (cs_opt_stackframe in current_settings.optimizerswitches) then
  55. include(flags,pi_needs_stackframe);
  56. floatregssave:=12; { f20-f31 }
  57. intregssave:=10; { r16-r23,r30,r31 }
  58. computed_local_size:=-1;
  59. { pi_needs_got is not yet set correctly
  60. so include it always if creating PIC code }
  61. if (cs_create_pic in current_settings.moduleswitches) then
  62. begin
  63. include(flags, pi_needs_got);
  64. got:=NR_GP;
  65. end
  66. else
  67. got:=NR_NO;
  68. end;
  69. procedure tcpuprocinfo.set_first_temp_offset;
  70. begin
  71. { MIPS stack frame is always "optimized" }
  72. framepointer:=NR_STACK_POINTER_REG;
  73. tg.direction:=1;
  74. { We allocate enough space to save all registers because we can't determine
  75. the necessary space because the used registers aren't known before
  76. secondpass is run. }
  77. { will call _mcount if profiling }
  78. if (cs_profile in current_settings.moduleswitches) and
  79. not (po_nostackframe in procdef.procoptions) then
  80. include(flags,pi_do_call);
  81. { Fixes the case when there are calls done by low-level means
  82. (cg.a_call_name) but no child callnode. !!For assembler procedure
  83. there is no clean way to determine what it calls, unless it is
  84. also declared as nostackframe and everything is managed manually. }
  85. if (pi_do_call in flags) or
  86. ((pi_is_assembler in flags) and not (po_nostackframe in procdef.procoptions)) then
  87. begin
  88. include(flags,pi_do_call); // for pi_is_assembler case
  89. allocate_push_parasize(mips_nb_used_registers*sizeof(aint));
  90. end;
  91. if not (po_nostackframe in procdef.procoptions) then
  92. tg.setfirsttemp(Align(maxpushedparasize+
  93. floatregssave*sizeof(aint)+intregssave*sizeof(aint)
  94. ,max(current_settings.alignment.localalignmin,8)))
  95. else
  96. tg.setfirsttemp(align(maxpushedparasize,max(current_settings.alignment.localalignmin,8)));
  97. end;
  98. procedure tcpuprocinfo.allocate_got_register(list:tasmlist);
  99. begin
  100. if (cs_create_pic in current_settings.moduleswitches) then
  101. begin
  102. if (pi_do_call in flags) then
  103. include(flags,pi_needs_got);
  104. if (pi_needs_got in flags) and
  105. not (po_nostackframe in procdef.procoptions) then
  106. tg.gettemp(list,sizeof(aint),sizeof(aint),tt_noreuse,save_gp_ref);
  107. end;
  108. end;
  109. function tcpuprocinfo.calc_stackframe_size:longint;
  110. begin
  111. result:=maxpushedparasize;
  112. floatregstart:=result;
  113. inc(result,floatregssave*4);
  114. intregstart:=result;
  115. //inc(result,intregssave*4);
  116. result:=Align(tg.lasttemp,max(current_settings.alignment.localalignmin,8));
  117. if computed_local_size=-1 then
  118. begin
  119. computed_local_size:=result;
  120. tcpuprocdef(procdef).total_local_size:=result;
  121. end
  122. else if computed_local_size <> result then
  123. Comment(V_Error,'tcpuprocinfo.calc_stackframe_size result changed');
  124. end;
  125. procedure tcpuprocinfo.postprocess_code;
  126. begin
  127. fixup_jmps(aktproccode);
  128. end;
  129. function mips_extra_offset(procdef : tprocdef) : longint;
  130. begin
  131. if procdef=nil then
  132. mips_extra_offset:=0
  133. else
  134. mips_extra_offset:=tcpuprocdef(procdef).total_local_size;
  135. end;
  136. begin
  137. cprocinfo:=tcpuprocinfo;
  138. end.