rgcpu.pas 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements the SPARC specific class for the register
  4. allocator
  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 by
  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. unit rgcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. aasmbase,aasmcpu,aasmtai,aasmdata,
  22. cgbase,cgutils,
  23. cpubase,
  24. globtype,
  25. rgobj;
  26. type
  27. trgcpu=class(trgobj)
  28. procedure do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
  29. procedure do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
  30. function get_spill_subreg(r: tregister): tsubregister; override;
  31. protected
  32. procedure do_spill_op(list: tasmlist; op: tasmop; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
  33. end;
  34. trgintcpu=class(trgcpu)
  35. procedure add_cpu_interferences(p: tai); override;
  36. end;
  37. implementation
  38. uses
  39. verbose,cutils,
  40. cgobj;
  41. function trgcpu.get_spill_subreg(r:tregister) : tsubregister;
  42. begin
  43. if (getregtype(r)<>R_MMREGISTER) then
  44. result:=defaultsub
  45. else
  46. result:=getsubreg(r);
  47. end;
  48. procedure trgcpu.do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
  49. begin
  50. do_spill_op(list,A_LDR,pos,spilltemp,tempreg,orgsupreg);
  51. end;
  52. procedure trgcpu.do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
  53. begin
  54. do_spill_op(list,A_STR,pos,spilltemp,tempreg,orgsupreg);
  55. end;
  56. procedure trgcpu.do_spill_op(list: tasmlist; op: tasmop; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
  57. var
  58. helpins : tai;
  59. tmpref : treference;
  60. helplist : TAsmList;
  61. hreg : tregister;
  62. isload : boolean;
  63. begin
  64. isload:=op=A_LDR;
  65. { offset out of range for regular load/store? }
  66. if simple_ref_type(op,reg_cgsize(tempreg),PF_None,spilltemp)<>sr_simple then
  67. begin
  68. helplist:=TAsmList.create;
  69. if getregtype(tempreg)=R_INTREGISTER then
  70. hreg:=tempreg
  71. else
  72. hreg:=cg.getaddressregister(helplist);
  73. cg.a_load_const_reg(helplist,OS_ADDR,spilltemp.offset,hreg);
  74. reference_reset_base(tmpref,spilltemp.base,0,spilltemp.temppos,sizeof(pint),[]);
  75. tmpref.index:=hreg;
  76. if isload then
  77. helpins:=spilling_create_load(tmpref,tempreg)
  78. else
  79. helpins:=spilling_create_store(tempreg,tmpref);
  80. helplist.concat(helpins);
  81. add_cpu_interferences(helpins);
  82. list.insertlistafter(pos,helplist);
  83. helplist.free;
  84. end
  85. else if isload then
  86. inherited do_spill_read(list,pos,spilltemp,tempreg,orgsupreg)
  87. else
  88. inherited do_spill_written(list,pos,spilltemp,tempreg,orgsupreg)
  89. end;
  90. procedure trgintcpu.add_cpu_interferences(p: tai);
  91. var
  92. i, j: longint;
  93. begin
  94. if p.typ=ait_instruction then
  95. begin
  96. { add interferences for instructions that can have SP as a register
  97. operand }
  98. case taicpu(p).opcode of
  99. A_MOV:
  100. { all operands can be SP }
  101. exit;
  102. A_ADD,
  103. A_SUB,
  104. A_CMP,
  105. A_CMN:
  106. { ok as destination or first source in immediate or extended
  107. register form }
  108. if (taicpu(p).oper[taicpu(p).ops-1]^.typ<>top_shifterop) or
  109. valid_shifter_operand(taicpu(p).opcode,false,true,
  110. reg_cgsize(taicpu(p).oper[0]^.reg) in [OS_64,OS_S64],
  111. taicpu(p).oper[taicpu(p).ops-1]^.shifterop^.shiftmode,
  112. taicpu(p).oper[taicpu(p).ops-1]^.shifterop^.shiftimm) then
  113. begin
  114. if taicpu(p).oper[taicpu(p).ops-1]^.typ=top_shifterop then
  115. i:=taicpu(p).ops-2
  116. else
  117. i:=taicpu(p).ops-1;
  118. if (taicpu(p).oper[i]^.typ=top_reg) then
  119. add_edge(getsupreg(taicpu(p).oper[i]^.reg),RS_SP);
  120. exit;
  121. end;
  122. A_AND,
  123. A_EOR,
  124. A_ORR,
  125. A_TST:
  126. { ok in immediate form }
  127. if taicpu(p).oper[taicpu(p).ops-1]^.typ=top_const then
  128. exit;
  129. end;
  130. { add interferences for other registers }
  131. for i:=0 to taicpu(p).ops-1 do
  132. begin
  133. case taicpu(p).oper[i]^.typ of
  134. top_reg:
  135. if getregtype(taicpu(p).oper[i]^.reg)=R_INTREGISTER then
  136. add_edge(getsupreg(taicpu(p).oper[i]^.reg),RS_SP);
  137. top_ref:
  138. begin
  139. { sp can always be base, never be index }
  140. if taicpu(p).oper[i]^.ref^.index<>NR_NO then
  141. add_edge(getsupreg(taicpu(p).oper[i]^.ref^.index),RS_SP);
  142. { in case of write back, the base register must be
  143. different from the loaded/stored register }
  144. if (taicpu(p).oper[i]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) and
  145. (taicpu(p).oper[i]^.ref^.base<>NR_NO) then
  146. begin
  147. for j:=pred(i) downto 0 do
  148. if taicpu(p).oper[j]^.typ=TOP_REG then
  149. add_edge(getsupreg(taicpu(p).oper[j]^.reg),getsupreg(taicpu(p).oper[i]^.ref^.base));
  150. end;
  151. end;
  152. end;
  153. end;
  154. end;
  155. end;
  156. end.