rgcpu.pas 9.9 KB

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