rgcpu.pas 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. {
  2. Copyright (c) 1998-2008 by Florian Klaempfl
  3. This unit implements the Z80 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. }
  18. unit rgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. aasmbase,aasmtai,aasmdata,aasmcpu,aasmsym,
  23. cgbase,cgutils,
  24. cpubase,
  25. rgobj;
  26. type
  27. trgcpu = class(trgobj)
  28. procedure add_constraints(reg:tregister);override;
  29. procedure do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
  30. procedure do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
  31. function do_spill_replace(list : TAsmList;instr : tai_cpu_abstract_sym; orgreg : tsuperregister;const spilltemp : treference) : boolean; override;
  32. end;
  33. trgintcpu = class(trgcpu)
  34. procedure add_cpu_interferences(p : tai);override;
  35. end;
  36. implementation
  37. uses
  38. verbose, cutils,
  39. cgobj,
  40. procinfo;
  41. procedure trgcpu.add_constraints(reg:tregister);
  42. var
  43. supreg,i : Tsuperregister;
  44. begin
  45. case getsubreg(reg) of
  46. R_SUBL,R_SUBH:
  47. begin
  48. { Some registers have no 8-bit subregister }
  49. supreg:=getsupreg(reg);
  50. add_edge(supreg,RS_IX);
  51. add_edge(supreg,RS_IY);
  52. add_edge(supreg,RS_SP);
  53. end;
  54. end;
  55. end;
  56. procedure trgcpu.do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
  57. var
  58. helpins : tai;
  59. tmpref : treference;
  60. helplist : TAsmList;
  61. hreg : tregister;
  62. begin
  63. if abs(spilltemp.offset)>127 then
  64. begin
  65. Internalerror(2017032701);
  66. //
  67. // helplist:=TAsmList.create;
  68. //
  69. // helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
  70. // helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
  71. // helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
  72. // helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,GetNextReg(spilltemp.base)));
  73. //
  74. // reference_reset_base(tmpref,NR_R26,0,1,[]);
  75. // helpins:=spilling_create_load(tmpref,tempreg);
  76. // helplist.concat(helpins);
  77. // list.insertlistafter(pos,helplist);
  78. // helplist.free;
  79. end
  80. else
  81. inherited;
  82. end;
  83. procedure trgcpu.do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
  84. var
  85. tmpref : treference;
  86. helplist : TAsmList;
  87. hreg : tregister;
  88. begin
  89. if abs(spilltemp.offset)>127 then
  90. begin
  91. Internalerror(2017032702);
  92. //
  93. // helplist:=TAsmList.create;
  94. //
  95. // helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
  96. // helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
  97. // helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
  98. // helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,GetNextReg(spilltemp.base)));
  99. //
  100. // reference_reset_base(tmpref,NR_R26,0,1,[]);
  101. // helplist.concat(spilling_create_store(tempreg,tmpref));
  102. // list.insertlistafter(pos,helplist);
  103. // helplist.free;
  104. end
  105. else
  106. inherited;
  107. end;
  108. procedure trgintcpu.add_cpu_interferences(p : tai);
  109. var
  110. r : tsuperregister;
  111. begin
  112. //if p.typ=ait_instruction then
  113. // begin
  114. // case taicpu(p).opcode of
  115. // A_CPI,
  116. // A_ANDI,
  117. // A_ORI,
  118. // A_SUBI,
  119. // A_SBCI,
  120. // A_LDI:
  121. // for r:=RS_R0 to RS_R15 do
  122. // add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg));
  123. // A_MULS:
  124. // begin
  125. // for r:=RS_R0 to RS_R15 do
  126. // add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg));
  127. // for r:=RS_R0 to RS_R15 do
  128. // add_edge(r,GetSupReg(taicpu(p).oper[1]^.reg));
  129. // end;
  130. // end;
  131. // end;
  132. end;
  133. function trgcpu.do_spill_replace(list:TAsmList;instr:tai_cpu_abstract_sym;orgreg:tsuperregister;const spilltemp:treference):boolean;
  134. var
  135. b : byte;
  136. begin
  137. result:=false;
  138. if not(spilltemp.offset in [-128..127]) then
  139. exit;
  140. { Replace 'ld orgreg,src' with 'ld spilltemp,src'
  141. and 'ld dst,orgreg' with 'ld dst,spilltemp' }
  142. with instr do
  143. begin
  144. if (opcode=A_LD) and (ops=2) and (oper[1]^.typ=top_reg) and (oper[0]^.typ=top_reg) then
  145. begin
  146. if (getregtype(oper[0]^.reg)=regtype) and
  147. (get_alias(getsupreg(oper[0]^.reg))=orgreg) and
  148. (get_alias(getsupreg(oper[1]^.reg))<>orgreg) then
  149. begin
  150. instr.loadref(0,spilltemp);
  151. opcode:=A_LD;
  152. result:=true;
  153. end
  154. else if (getregtype(oper[1]^.reg)=regtype) and
  155. (get_alias(getsupreg(oper[1]^.reg))=orgreg) and
  156. (get_alias(getsupreg(oper[0]^.reg))<>orgreg) then
  157. begin
  158. instr.loadref(1,spilltemp);
  159. opcode:=A_LD;
  160. result:=true;
  161. end;
  162. end
  163. { Replace 'ld orgreg,const' with 'ld spilltemp,const' }
  164. else if (opcode=A_LD) and (ops=2) and (oper[1]^.typ=top_const) and (oper[0]^.typ=top_reg) then
  165. begin
  166. if (getregtype(oper[0]^.reg)=regtype) and
  167. (get_alias(getsupreg(oper[0]^.reg))=orgreg) then
  168. begin
  169. instr.loadref(0,spilltemp);
  170. opcode:=A_LD;
  171. result:=true;
  172. end;
  173. end
  174. { Replace 'add A,orgreg' with 'add A,spilltemp'
  175. and 'adc A,orgreg' with 'adc A,spilltemp'
  176. and 'sub A,orgreg' with 'sub A,spilltemp'
  177. and 'sbc A,orgreg' with 'sbc A,spilltemp'
  178. and 'and A,orgreg' with 'and A,spilltemp'
  179. and 'or A,orgreg' with 'or A,spilltemp'
  180. and 'xor A,orgreg' with 'xor A,spilltemp'
  181. and 'cp A,orgreg' with 'cp A,spilltemp'
  182. }
  183. else if (opcode in [A_ADD,A_ADC,A_SUB,A_SBC,A_AND,A_OR,A_XOR,A_CP]) and (ops=2) and (oper[1]^.typ=top_reg) and (oper[0]^.typ=top_reg) then
  184. begin
  185. { we don't really need to check whether the first register is 'A',
  186. because that's the only register allowed as a destination for
  187. these instructions }
  188. if (getregtype(oper[1]^.reg)=regtype) and
  189. (get_alias(getsupreg(oper[1]^.reg))=orgreg) and
  190. (get_alias(getsupreg(oper[0]^.reg))<>orgreg) then
  191. begin
  192. instr.loadref(1,spilltemp);
  193. result:=true;
  194. end;
  195. end
  196. { Replace 'inc orgreg' with 'inc spilltemp'
  197. and 'dec orgreg' with 'dec spilltemp'
  198. and 'add orgreg' with 'add spilltemp'
  199. and 'adc orgreg' with 'adc spilltemp'
  200. and 'sub orgreg' with 'sub spilltemp'
  201. and 'sbc orgreg' with 'sbc spilltemp'
  202. and 'and orgreg' with 'and spilltemp'
  203. and 'or orgreg' with 'or spilltemp'
  204. and 'xor orgreg' with 'xor spilltemp'
  205. and 'cp orgreg' with 'cp spilltemp' }
  206. else if (opcode in [A_INC,A_DEC,A_ADD,A_ADC,A_SUB,A_SBC,A_AND,A_OR,A_XOR,A_CP]) and (ops=1) and (oper[0]^.typ=top_reg) then
  207. begin
  208. if (getregtype(oper[0]^.reg)=regtype) and
  209. (get_alias(getsupreg(oper[0]^.reg))=orgreg) then
  210. begin
  211. instr.loadref(0,spilltemp);
  212. result:=true;
  213. end;
  214. end;
  215. end;
  216. end;
  217. end.