rgcpu.pas 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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. else
  55. ;
  56. end;
  57. end;
  58. procedure trgcpu.do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
  59. var
  60. helpins : tai;
  61. tmpref : treference;
  62. helplist : TAsmList;
  63. hreg : tregister;
  64. begin
  65. // if abs(spilltemp.offset)>127 then
  66. // begin
  67. // Internalerror(2017032701);
  68. //
  69. // helplist:=TAsmList.create;
  70. //
  71. // helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
  72. // helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
  73. // helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
  74. // helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,GetNextReg(spilltemp.base)));
  75. //
  76. // reference_reset_base(tmpref,NR_R26,0,1,[]);
  77. // helpins:=spilling_create_load(tmpref,tempreg);
  78. // helplist.concat(helpins);
  79. // list.insertlistafter(pos,helplist);
  80. // helplist.free;
  81. // end
  82. // else
  83. inherited;
  84. end;
  85. procedure trgcpu.do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
  86. var
  87. tmpref : treference;
  88. helplist : TAsmList;
  89. hreg : tregister;
  90. begin
  91. // if abs(spilltemp.offset)>127 then
  92. // begin
  93. // Internalerror(2017032702);
  94. //
  95. // helplist:=TAsmList.create;
  96. //
  97. // helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
  98. // helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
  99. // helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
  100. // helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,GetNextReg(spilltemp.base)));
  101. //
  102. // reference_reset_base(tmpref,NR_R26,0,1,[]);
  103. // helplist.concat(spilling_create_store(tempreg,tmpref));
  104. // list.insertlistafter(pos,helplist);
  105. // helplist.free;
  106. // end
  107. // else
  108. inherited;
  109. end;
  110. procedure trgintcpu.add_cpu_interferences(p : tai);
  111. var
  112. r : tsuperregister;
  113. begin
  114. //if p.typ=ait_instruction then
  115. // begin
  116. // case taicpu(p).opcode of
  117. // A_CPI,
  118. // A_ANDI,
  119. // A_ORI,
  120. // A_SUBI,
  121. // A_SBCI,
  122. // A_LDI:
  123. // for r:=RS_R0 to RS_R15 do
  124. // add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg));
  125. // A_MULS:
  126. // begin
  127. // for r:=RS_R0 to RS_R15 do
  128. // add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg));
  129. // for r:=RS_R0 to RS_R15 do
  130. // add_edge(r,GetSupReg(taicpu(p).oper[1]^.reg));
  131. // end;
  132. // end;
  133. // end;
  134. end;
  135. function trgcpu.do_spill_replace(list:TAsmList;instr:tai_cpu_abstract_sym;orgreg:tsuperregister;const spilltemp:treference):boolean;
  136. var
  137. b : byte;
  138. begin
  139. result:=false;
  140. if (spilltemp.offset<-128) or (spilltemp.offset>127) then
  141. exit;
  142. { Replace 'ld orgreg,src' with 'ld spilltemp,src'
  143. and 'ld dst,orgreg' with 'ld dst,spilltemp' }
  144. with instr do
  145. begin
  146. if (opcode=A_LD) and (ops=2) and (oper[1]^.typ=top_reg) and (oper[0]^.typ=top_reg) then
  147. begin
  148. if (getregtype(oper[0]^.reg)=regtype) and
  149. (get_alias(getsupreg(oper[0]^.reg))=orgreg) and
  150. (get_alias(getsupreg(oper[1]^.reg))<>orgreg) then
  151. begin
  152. instr.loadref(0,spilltemp);
  153. result:=true;
  154. end
  155. else if (getregtype(oper[1]^.reg)=regtype) and
  156. (get_alias(getsupreg(oper[1]^.reg))=orgreg) and
  157. (get_alias(getsupreg(oper[0]^.reg))<>orgreg) then
  158. begin
  159. instr.loadref(1,spilltemp);
  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. result:=true;
  171. end;
  172. end
  173. { Replace 'add A,orgreg' with 'add A,spilltemp'
  174. and 'adc A,orgreg' with 'adc A,spilltemp'
  175. and 'sub A,orgreg' with 'sub A,spilltemp'
  176. and 'sbc A,orgreg' with 'sbc A,spilltemp'
  177. and 'and A,orgreg' with 'and A,spilltemp'
  178. and 'or A,orgreg' with 'or A,spilltemp'
  179. and 'xor A,orgreg' with 'xor A,spilltemp'
  180. and 'cp A,orgreg' with 'cp A,spilltemp' }
  181. 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
  182. begin
  183. { we don't really need to check whether the first register is 'A',
  184. because that's the only register allowed as a destination for
  185. these instructions }
  186. if (getregtype(oper[1]^.reg)=regtype) and
  187. (get_alias(getsupreg(oper[1]^.reg))=orgreg) and
  188. (get_alias(getsupreg(oper[0]^.reg))<>orgreg) then
  189. begin
  190. instr.loadref(1,spilltemp);
  191. result:=true;
  192. end;
  193. end
  194. { Replace 'bit const,orgreg' with 'bit const,spilltemp'
  195. and 'set const,orgreg' with 'set const,spilltemp'
  196. and 'res const,orgreg' with 'res const,spilltemp' }
  197. else if (opcode in [A_BIT,A_SET,A_RES]) and (ops=2) and (oper[1]^.typ=top_reg) and (oper[0]^.typ=top_const) then
  198. begin
  199. if (getregtype(oper[1]^.reg)=regtype) and
  200. (get_alias(getsupreg(oper[1]^.reg))=orgreg) then
  201. begin
  202. instr.loadref(1,spilltemp);
  203. result:=true;
  204. end;
  205. end
  206. { Replace 'inc orgreg' with 'inc spilltemp'
  207. and 'dec orgreg' with 'dec spilltemp'
  208. and 'add orgreg' with 'add spilltemp'
  209. and 'adc orgreg' with 'adc spilltemp'
  210. and 'sub orgreg' with 'sub spilltemp'
  211. and 'sbc orgreg' with 'sbc spilltemp'
  212. and 'and orgreg' with 'and spilltemp'
  213. and 'or orgreg' with 'or spilltemp'
  214. and 'xor orgreg' with 'xor spilltemp'
  215. and 'cp orgreg' with 'cp spilltemp'
  216. and 'rlc orgreg' with 'rlc spilltemp'
  217. and 'rl orgreg' with 'rl spilltemp'
  218. and 'rrc orgreg' with 'rrc spilltemp'
  219. and 'rr orgreg' with 'rr spilltemp'
  220. and 'sla orgreg' with 'sla spilltemp'
  221. and 'sra orgreg' with 'sra spilltemp'
  222. and 'srl orgreg' with 'srl spilltemp' }
  223. else if (opcode in [A_INC,A_DEC,A_ADD,A_ADC,A_SUB,A_SBC,A_AND,A_OR,A_XOR,A_CP,
  224. A_RLC,A_RL,A_RRC,A_RR,A_SLA,A_SRA,A_SRL]) and (ops=1) and (oper[0]^.typ=top_reg) then
  225. begin
  226. if (getregtype(oper[0]^.reg)=regtype) and
  227. (get_alias(getsupreg(oper[0]^.reg))=orgreg) then
  228. begin
  229. instr.loadref(0,spilltemp);
  230. result:=true;
  231. end;
  232. end;
  233. end;
  234. end;
  235. end.