rgcpu.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. {
  2. Copyright (c) 1998-2003 by Florian Klaempfl
  3. This unit implements the arm 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,
  23. cgbase,cgutils,
  24. cpubase,
  25. rgobj;
  26. type
  27. trgcpu = class(trgobj)
  28. procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
  29. procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
  30. procedure add_constraints(reg:tregister);override;
  31. function get_spill_subreg(r:tregister) : tsubregister;override;
  32. end;
  33. trgcputhumb2 = class(trgobj)
  34. procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
  35. procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
  36. end;
  37. trgintcpu = class(trgcpu)
  38. procedure add_cpu_interferences(p : tai);override;
  39. end;
  40. implementation
  41. uses
  42. verbose, cutils,globtype,
  43. cgobj,
  44. procinfo;
  45. procedure trgcpu.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
  46. var
  47. tmpref : treference;
  48. helplist : TAsmList;
  49. l : tasmlabel;
  50. hreg : tregister;
  51. begin
  52. { don't load spilled register between
  53. mov lr,pc
  54. mov pc,r4
  55. but befure the mov lr,pc
  56. }
  57. if assigned(pos.previous) and
  58. (pos.typ=ait_instruction) and
  59. (taicpu(pos).opcode=A_MOV) and
  60. (taicpu(pos).oper[0]^.typ=top_reg) and
  61. (taicpu(pos).oper[0]^.reg=NR_R14) and
  62. (taicpu(pos).oper[1]^.typ=top_reg) and
  63. (taicpu(pos).oper[1]^.reg=NR_PC) then
  64. pos:=tai(pos.previous);
  65. if abs(spilltemp.offset)>4095 then
  66. begin
  67. helplist:=TAsmList.create;
  68. reference_reset(tmpref,sizeof(aint));
  69. { create consts entry }
  70. current_asmdata.getjumplabel(l);
  71. cg.a_label(current_procinfo.aktlocaldata,l);
  72. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  73. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
  74. { load consts entry }
  75. if getregtype(tempreg)=R_INTREGISTER then
  76. hreg:=getregisterinline(helplist,R_SUBWHOLE)
  77. else
  78. hreg:=cg.getintregister(helplist,OS_ADDR);
  79. tmpref.symbol:=l;
  80. tmpref.base:=NR_R15;
  81. helplist.concat(taicpu.op_reg_ref(A_LDR,hreg,tmpref));
  82. reference_reset_base(tmpref,current_procinfo.framepointer,0,sizeof(aint));
  83. tmpref.index:=hreg;
  84. if spilltemp.index<>NR_NO then
  85. internalerror(200401263);
  86. helplist.concat(spilling_create_load(tmpref,tempreg));
  87. if getregtype(tempreg)=R_INTREGISTER then
  88. ungetregisterinline(helplist,hreg);
  89. list.insertlistafter(pos,helplist);
  90. helplist.free;
  91. end
  92. else
  93. inherited do_spill_read(list,pos,spilltemp,tempreg);
  94. end;
  95. procedure trgcpu.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
  96. var
  97. tmpref : treference;
  98. helplist : TAsmList;
  99. l : tasmlabel;
  100. hreg : tregister;
  101. begin
  102. if abs(spilltemp.offset)>4095 then
  103. begin
  104. helplist:=TAsmList.create;
  105. reference_reset(tmpref,sizeof(aint));
  106. { create consts entry }
  107. current_asmdata.getjumplabel(l);
  108. cg.a_label(current_procinfo.aktlocaldata,l);
  109. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  110. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
  111. { load consts entry }
  112. if getregtype(tempreg)=R_INTREGISTER then
  113. hreg:=getregisterinline(helplist,R_SUBWHOLE)
  114. else
  115. hreg:=cg.getintregister(helplist,OS_ADDR);
  116. tmpref.symbol:=l;
  117. tmpref.base:=NR_R15;
  118. helplist.concat(taicpu.op_reg_ref(A_LDR,hreg,tmpref));
  119. if spilltemp.index<>NR_NO then
  120. internalerror(200401263);
  121. reference_reset_base(tmpref,current_procinfo.framepointer,0,sizeof(pint));
  122. tmpref.index:=hreg;
  123. helplist.concat(spilling_create_store(tempreg,tmpref));
  124. if getregtype(tempreg)=R_INTREGISTER then
  125. ungetregisterinline(helplist,hreg);
  126. list.insertlistafter(pos,helplist);
  127. helplist.free;
  128. end
  129. else
  130. inherited do_spill_written(list,pos,spilltemp,tempreg);
  131. end;
  132. procedure trgcpu.add_constraints(reg:tregister);
  133. var
  134. supreg,i : Tsuperregister;
  135. begin
  136. case getsubreg(reg) of
  137. { Let 32bit floats conflict with all double precision regs > 15
  138. (since these don't have 32 bit equivalents) }
  139. R_SUBFS:
  140. begin
  141. supreg:=getsupreg(reg);
  142. for i:=RS_D16 to RS_D31 do
  143. add_edge(supreg,i);
  144. end;
  145. end;
  146. end;
  147. function trgcpu.get_spill_subreg(r:tregister) : tsubregister;
  148. begin
  149. if (getregtype(r)<>R_MMREGISTER) then
  150. result:=defaultsub
  151. else
  152. result:=getsubreg(r);
  153. end;
  154. procedure trgcputhumb2.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
  155. var
  156. tmpref : treference;
  157. helplist : TAsmList;
  158. l : tasmlabel;
  159. hreg : tregister;
  160. begin
  161. { don't load spilled register between
  162. mov lr,pc
  163. mov pc,r4
  164. but befure the mov lr,pc
  165. }
  166. if assigned(pos.previous) and
  167. (pos.typ=ait_instruction) and
  168. (taicpu(pos).opcode=A_MOV) and
  169. (taicpu(pos).oper[0]^.typ=top_reg) and
  170. (taicpu(pos).oper[0]^.reg=NR_R14) and
  171. (taicpu(pos).oper[1]^.typ=top_reg) and
  172. (taicpu(pos).oper[1]^.reg=NR_PC) then
  173. pos:=tai(pos.previous);
  174. if (spilltemp.offset>4095) or (spilltemp.offset<-255) then
  175. begin
  176. helplist:=TAsmList.create;
  177. reference_reset(tmpref,sizeof(aint));
  178. { create consts entry }
  179. current_asmdata.getjumplabel(l);
  180. cg.a_label(current_procinfo.aktlocaldata,l);
  181. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  182. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
  183. { load consts entry }
  184. if getregtype(tempreg)=R_INTREGISTER then
  185. hreg:=getregisterinline(helplist,R_SUBWHOLE)
  186. else
  187. hreg:=cg.getintregister(helplist,OS_ADDR);
  188. tmpref.symbol:=l;
  189. tmpref.base:=NR_R15;
  190. helplist.concat(taicpu.op_reg_ref(A_LDR,hreg,tmpref));
  191. reference_reset_base(tmpref,current_procinfo.framepointer,0,sizeof(aint));
  192. tmpref.index:=hreg;
  193. if spilltemp.index<>NR_NO then
  194. internalerror(200401263);
  195. helplist.concat(spilling_create_load(tmpref,tempreg));
  196. if getregtype(tempreg)=R_INTREGISTER then
  197. ungetregisterinline(helplist,hreg);
  198. list.insertlistafter(pos,helplist);
  199. helplist.free;
  200. end
  201. else
  202. inherited do_spill_read(list,pos,spilltemp,tempreg);
  203. end;
  204. procedure trgcputhumb2.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
  205. var
  206. tmpref : treference;
  207. helplist : TAsmList;
  208. l : tasmlabel;
  209. hreg : tregister;
  210. begin
  211. if (spilltemp.offset>4095) or (spilltemp.offset<-255) then
  212. begin
  213. helplist:=TAsmList.create;
  214. reference_reset(tmpref,sizeof(aint));
  215. { create consts entry }
  216. current_asmdata.getjumplabel(l);
  217. cg.a_label(current_procinfo.aktlocaldata,l);
  218. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  219. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
  220. { load consts entry }
  221. if getregtype(tempreg)=R_INTREGISTER then
  222. hreg:=getregisterinline(helplist,R_SUBWHOLE)
  223. else
  224. hreg:=cg.getintregister(helplist,OS_ADDR);
  225. tmpref.symbol:=l;
  226. tmpref.base:=NR_R15;
  227. helplist.concat(taicpu.op_reg_ref(A_LDR,hreg,tmpref));
  228. if spilltemp.index<>NR_NO then
  229. internalerror(200401263);
  230. reference_reset_base(tmpref,current_procinfo.framepointer,0,sizeof(pint));
  231. tmpref.index:=hreg;
  232. helplist.concat(spilling_create_store(tempreg,tmpref));
  233. if getregtype(tempreg)=R_INTREGISTER then
  234. ungetregisterinline(helplist,hreg);
  235. list.insertlistafter(pos,helplist);
  236. helplist.free;
  237. end
  238. else
  239. inherited do_spill_written(list,pos,spilltemp,tempreg);
  240. end;
  241. procedure trgintcpu.add_cpu_interferences(p : tai);
  242. var
  243. r : tregister;
  244. begin
  245. if p.typ=ait_instruction then
  246. begin
  247. case taicpu(p).opcode of
  248. A_MUL:
  249. add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
  250. A_UMULL,
  251. A_UMLAL,
  252. A_SMULL,
  253. A_SMLAL:
  254. begin
  255. add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
  256. add_edge(getsupreg(taicpu(p).oper[1]^.reg),getsupreg(taicpu(p).oper[2]^.reg));
  257. add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[2]^.reg));
  258. end;
  259. A_LDRB,
  260. A_STRB,
  261. A_STR,
  262. A_LDR,
  263. A_LDRH,
  264. A_STRH:
  265. { don't mix up the framepointer and stackpointer with pre/post indexed operations }
  266. if (taicpu(p).oper[1]^.typ=top_ref) and
  267. (taicpu(p).oper[1]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) then
  268. begin
  269. add_edge(getsupreg(taicpu(p).oper[1]^.ref^.base),getsupreg(current_procinfo.framepointer));
  270. { FIXME: temp variable r is needed here to avoid Internal error 20060521 }
  271. { while compiling the compiler. }
  272. r:=NR_STACK_POINTER_REG;
  273. if current_procinfo.framepointer<>r then
  274. add_edge(getsupreg(taicpu(p).oper[1]^.ref^.base),getsupreg(r));
  275. end;
  276. end;
  277. end;
  278. end;
  279. end.