rgcpu.pas 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. result:=true;
  152. end
  153. else if (getregtype(oper[1]^.reg)=regtype) and
  154. (get_alias(getsupreg(oper[1]^.reg))=orgreg) and
  155. (get_alias(getsupreg(oper[0]^.reg))<>orgreg) then
  156. begin
  157. instr.loadref(1,spilltemp);
  158. result:=true;
  159. end;
  160. end
  161. { Replace 'ld orgreg,const' with 'ld spilltemp,const' }
  162. else if (opcode=A_LD) and (ops=2) and (oper[1]^.typ=top_const) and (oper[0]^.typ=top_reg) then
  163. begin
  164. if (getregtype(oper[0]^.reg)=regtype) and
  165. (get_alias(getsupreg(oper[0]^.reg))=orgreg) then
  166. begin
  167. instr.loadref(0,spilltemp);
  168. result:=true;
  169. end;
  170. end
  171. { Replace 'add A,orgreg' with 'add A,spilltemp'
  172. and 'adc A,orgreg' with 'adc A,spilltemp'
  173. and 'sub A,orgreg' with 'sub A,spilltemp'
  174. and 'sbc A,orgreg' with 'sbc A,spilltemp'
  175. and 'and A,orgreg' with 'and A,spilltemp'
  176. and 'or A,orgreg' with 'or A,spilltemp'
  177. and 'xor A,orgreg' with 'xor A,spilltemp'
  178. and 'cp A,orgreg' with 'cp A,spilltemp' }
  179. 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
  180. begin
  181. { we don't really need to check whether the first register is 'A',
  182. because that's the only register allowed as a destination for
  183. these instructions }
  184. if (getregtype(oper[1]^.reg)=regtype) and
  185. (get_alias(getsupreg(oper[1]^.reg))=orgreg) and
  186. (get_alias(getsupreg(oper[0]^.reg))<>orgreg) then
  187. begin
  188. instr.loadref(1,spilltemp);
  189. result:=true;
  190. end;
  191. end
  192. { Replace 'bit const,orgreg' with 'bit const,spilltemp'
  193. and 'set const,orgreg' with 'set const,spilltemp'
  194. and 'res const,orgreg' with 'res const,spilltemp' }
  195. 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
  196. begin
  197. if (getregtype(oper[1]^.reg)=regtype) and
  198. (get_alias(getsupreg(oper[1]^.reg))=orgreg) then
  199. begin
  200. instr.loadref(1,spilltemp);
  201. result:=true;
  202. end;
  203. end
  204. { Replace 'inc orgreg' with 'inc spilltemp'
  205. and 'dec orgreg' with 'dec spilltemp'
  206. and 'add orgreg' with 'add spilltemp'
  207. and 'adc orgreg' with 'adc spilltemp'
  208. and 'sub orgreg' with 'sub spilltemp'
  209. and 'sbc orgreg' with 'sbc spilltemp'
  210. and 'and orgreg' with 'and spilltemp'
  211. and 'or orgreg' with 'or spilltemp'
  212. and 'xor orgreg' with 'xor spilltemp'
  213. and 'cp orgreg' with 'cp spilltemp'
  214. and 'rlc orgreg' with 'rlc spilltemp'
  215. and 'rl orgreg' with 'rl spilltemp'
  216. and 'rrc orgreg' with 'rrc spilltemp'
  217. and 'rr orgreg' with 'rr spilltemp'
  218. and 'sla orgreg' with 'sla spilltemp'
  219. and 'sra orgreg' with 'sra spilltemp'
  220. and 'srl orgreg' with 'srl spilltemp' }
  221. else if (opcode in [A_INC,A_DEC,A_ADD,A_ADC,A_SUB,A_SBC,A_AND,A_OR,A_XOR,A_CP,
  222. A_RLC,A_RL,A_RRC,A_RR,A_SLA,A_SRA,A_SRL]) and (ops=1) and (oper[0]^.typ=top_reg) then
  223. begin
  224. if (getregtype(oper[0]^.reg)=regtype) and
  225. (get_alias(getsupreg(oper[0]^.reg))=orgreg) then
  226. begin
  227. instr.loadref(0,spilltemp);
  228. result:=true;
  229. end;
  230. end;
  231. end;
  232. end;
  233. end.