rgx86.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the x86 specific class for the register
  5. allocator
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit rgx86;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. cpubase,
  24. cpuinfo,
  25. aasmbase,aasmtai,
  26. cclasses,globtype,cgbase,rgobj;
  27. type
  28. trgx86 = class(trgobj)
  29. function instr_spill_register(list:Taasmoutput;
  30. instr:taicpu_abstract;
  31. const r:Tsuperregisterset;
  32. const spilltemplist:Tspill_temp_list): boolean;override;
  33. end;
  34. tpushedsavedloc = record
  35. case byte of
  36. 0: (pushed: boolean);
  37. 1: (ofs: longint);
  38. end;
  39. tpushedsavedfpu = array[tsuperregister] of tpushedsavedloc;
  40. trgx86fpu = class
  41. { The "usableregsxxx" contain all registers of type "xxx" that }
  42. { aren't currently allocated to a regvar. The "unusedregsxxx" }
  43. { contain all registers of type "xxx" that aren't currently }
  44. { allocated }
  45. unusedregsfpu,usableregsfpu : Tsuperregisterset;
  46. { these counters contain the number of elements in the }
  47. { unusedregsxxx/usableregsxxx sets }
  48. countunusedregsfpu : byte;
  49. { Contains the registers which are really used by the proc itself.
  50. It doesn't take care of registers used by called procedures
  51. }
  52. used_in_proc : tcpuregisterset;
  53. {reg_pushes_other : regvarother_longintarray;
  54. is_reg_var_other : regvarother_booleanarray;
  55. regvar_loaded_other : regvarother_booleanarray;}
  56. { tries to hold the amount of times which the current tree is processed }
  57. t_times: longint;
  58. fpuvaroffset : byte;
  59. constructor create;
  60. function getregisterfpu(list: taasmoutput) : tregister;
  61. procedure ungetregisterfpu(list: taasmoutput; r : tregister);
  62. { pushes and restores registers }
  63. procedure saveusedfpuregisters(list:Taasmoutput;
  64. var saved:Tpushedsavedfpu;
  65. const s:Tcpuregisterset);
  66. procedure restoreusedfpuregisters(list:Taasmoutput;
  67. const saved:Tpushedsavedfpu);
  68. { corrects the fpu stack register by ofs }
  69. function correct_fpuregister(r : tregister;ofs : byte) : tregister;
  70. end;
  71. implementation
  72. uses
  73. systems,
  74. verbose,
  75. aasmcpu;
  76. const
  77. { This value is used in tsaved. If the array value is equal
  78. to this, then this means that this register is not used.}
  79. reg_not_saved = $7fffffff;
  80. {******************************************************************************
  81. Trgcpu
  82. ******************************************************************************}
  83. function trgx86.instr_spill_register(list:Taasmoutput;
  84. instr:taicpu_abstract;
  85. const r:Tsuperregisterset;
  86. const spilltemplist:Tspill_temp_list): boolean;
  87. {
  88. Spill the registers in r in this instruction. Returns true if any help
  89. registers are used. This procedure has become one big hack party, because
  90. of the huge amount of situations you can have. The irregularity of the i386
  91. instruction set doesn't help either. (DM)
  92. }
  93. var i:byte;
  94. supreg:Tsuperregister;
  95. subreg:Tsubregister;
  96. helpreg:Tregister;
  97. helpins:Taicpu;
  98. op:Tasmop;
  99. hopsize:Topsize;
  100. pos:Tai;
  101. begin
  102. {Situation examples are in intel notation, so operand order:
  103. mov eax , ebx
  104. ^^^ ^^^
  105. oper[1] oper[0]
  106. (DM)}
  107. result:=false;
  108. with taicpu(instr) do
  109. begin
  110. case ops of
  111. 1:
  112. begin
  113. if (oper[0]^.typ=top_reg) and
  114. (getregtype(oper[0]^.reg)=regtype) then
  115. begin
  116. supreg:=getsupreg(oper[0]^.reg);
  117. if supregset_in(r,supreg) then
  118. begin
  119. {Situation example:
  120. push r20d ; r20d must be spilled into [ebp-12]
  121. Change into:
  122. push [ebp-12] ; Replace register by reference }
  123. { hopsize:=reg2opsize(oper[0].reg);}
  124. oper[0]^.typ:=top_ref;
  125. new(oper[0]^.ref);
  126. oper[0]^.ref^:=spilltemplist[supreg];
  127. { oper[0]^.ref^.size:=hopsize;}
  128. end;
  129. end;
  130. if oper[0]^.typ=top_ref then
  131. begin
  132. supreg:=getsupreg(oper[0]^.ref^.base);
  133. if supregset_in(r,supreg) then
  134. begin
  135. {Situation example:
  136. push [r21d+4*r22d] ; r21d must be spilled into [ebp-12]
  137. Change into:
  138. mov r23d,[ebp-12] ; Use a help register
  139. push [r23d+4*r22d] ; Replace register by helpregister }
  140. subreg:=getsubreg(oper[0]^.ref^.base);
  141. if oper[0]^.ref^.index=NR_NO then
  142. pos:=Tai(previous)
  143. else
  144. pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.index),RS_INVALID,RS_INVALID);
  145. getregisterinline(list,pos,subreg,helpreg);
  146. result:=true;
  147. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.base),spilltemplist[supreg],helpreg);
  148. if pos=nil then
  149. list.insertafter(helpins,list.first)
  150. else
  151. list.insertafter(helpins,pos.next);
  152. ungetregisterinline(list,helpins,helpreg);
  153. forward_allocation(Tai(helpins.next),instr);
  154. oper[0]^.ref^.base:=helpreg;
  155. end;
  156. supreg:=getsupreg(oper[0]^.ref^.index);
  157. if supregset_in(r,supreg) then
  158. begin
  159. {Situation example:
  160. push [r21d+4*r22d] ; r22d must be spilled into [ebp-12]
  161. Change into:
  162. mov r23d,[ebp-12] ; Use a help register
  163. push [r21d+4*r23d] ; Replace register by helpregister }
  164. subreg:=getsubreg(oper[0]^.ref^.index);
  165. if oper[0]^.ref^.base=NR_NO then
  166. pos:=Tai(instr.previous)
  167. else
  168. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),RS_INVALID,RS_INVALID);
  169. getregisterinline(list,pos,subreg,helpreg);
  170. result:=true;
  171. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.index),spilltemplist[supreg],helpreg);
  172. if pos=nil then
  173. list.insertafter(helpins,list.first)
  174. else
  175. list.insertafter(helpins,pos.next);
  176. ungetregisterinline(list,helpins,helpreg);
  177. forward_allocation(Tai(helpins.next),instr);
  178. oper[0]^.ref^.index:=helpreg;
  179. end;
  180. end;
  181. end;
  182. 2:
  183. begin
  184. { First spill the registers from the references. This is
  185. required because the reference can be moved from this instruction
  186. to a MOV instruction when spilling of the register operand is done }
  187. for i:=0 to 1 do
  188. if oper[i]^.typ=top_ref then
  189. begin
  190. supreg:=getsupreg(oper[i]^.ref^.base);
  191. if supregset_in(r,supreg) then
  192. begin
  193. {Situation example:
  194. add r20d,[r21d+4*r22d] ; r21d must be spilled into [ebp-12]
  195. Change into:
  196. mov r23d,[ebp-12] ; Use a help register
  197. add r20d,[r23d+4*r22d] ; Replace register by helpregister }
  198. subreg:=getsubreg(oper[i]^.ref^.base);
  199. if i=1 then
  200. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),getsupreg(oper[0]^.reg),RS_INVALID)
  201. else
  202. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),RS_INVALID,RS_INVALID);
  203. getregisterinline(list,pos,subreg,helpreg);
  204. result:=true;
  205. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.base),spilltemplist[supreg],helpreg);
  206. if pos=nil then
  207. list.insertafter(helpins,list.first)
  208. else
  209. list.insertafter(helpins,pos.next);
  210. oper[i]^.ref^.base:=helpreg;
  211. ungetregisterinline(list,helpins,helpreg);
  212. forward_allocation(Tai(helpins.next),instr);
  213. end;
  214. supreg:=getsupreg(oper[i]^.ref^.index);
  215. if supregset_in(r,supreg) then
  216. begin
  217. {Situation example:
  218. add r20d,[r21d+4*r22d] ; r22d must be spilled into [ebp-12]
  219. Change into:
  220. mov r23d,[ebp-12] ; Use a help register
  221. add r20d,[r21d+4*r23d] ; Replace register by helpregister }
  222. subreg:=getsubreg(oper[i]^.ref^.index);
  223. if i=1 then
  224. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),
  225. getsupreg(oper[0]^.reg),RS_INVALID)
  226. else
  227. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),RS_INVALID,RS_INVALID);
  228. getregisterinline(list,pos,subreg,helpreg);
  229. result:=true;
  230. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.index),spilltemplist[supreg],helpreg);
  231. if pos=nil then
  232. list.insertafter(helpins,list.first)
  233. else
  234. list.insertafter(helpins,pos.next);
  235. oper[i]^.ref^.index:=helpreg;
  236. ungetregisterinline(list,helpins,helpreg);
  237. forward_allocation(Tai(helpins.next),instr);
  238. end;
  239. end;
  240. if (oper[0]^.typ=top_reg) and
  241. (getregtype(oper[0]^.reg)=regtype) then
  242. begin
  243. supreg:=getsupreg(oper[0]^.reg);
  244. subreg:=getsubreg(oper[0]^.reg);
  245. if supregset_in(r,supreg) then
  246. if oper[1]^.typ=top_ref then
  247. begin
  248. {Situation example:
  249. add [r20d],r21d ; r21d must be spilled into [ebp-12]
  250. Change into:
  251. mov r22d,[ebp-12] ; Use a help register
  252. add [r20d],r22d ; Replace register by helpregister }
  253. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),
  254. getsupreg(oper[1]^.ref^.base),getsupreg(oper[1]^.ref^.index));
  255. getregisterinline(list,pos,subreg,helpreg);
  256. result:=true;
  257. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.reg),spilltemplist[supreg],helpreg);
  258. if pos=nil then
  259. list.insertafter(helpins,list.first)
  260. else
  261. list.insertafter(helpins,pos.next);
  262. oper[0]^.reg:=helpreg;
  263. ungetregisterinline(list,helpins,helpreg);
  264. forward_allocation(Tai(helpins.next),instr);
  265. end
  266. else
  267. begin
  268. {Situation example:
  269. add r20d,r21d ; r21d must be spilled into [ebp-12]
  270. Change into:
  271. add r20d,[ebp-12] ; Replace register by reference }
  272. oper[0]^.typ:=top_ref;
  273. new(oper[0]^.ref);
  274. oper[0]^.ref^:=spilltemplist[supreg];
  275. end;
  276. end;
  277. if (oper[1]^.typ=top_reg) and
  278. (getregtype(oper[1]^.reg)=regtype) then
  279. begin
  280. supreg:=getsupreg(oper[1]^.reg);
  281. subreg:=getsubreg(oper[1]^.reg);
  282. if supregset_in(r,supreg) then
  283. begin
  284. if oper[0]^.typ=top_ref then
  285. begin
  286. {Situation example:
  287. add r20d,[r21d] ; r20d must be spilled into [ebp-12]
  288. Change into:
  289. mov r22d,[r21d] ; Use a help register
  290. add [ebp-12],r22d ; Replace register by helpregister }
  291. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),
  292. getsupreg(oper[0]^.ref^.index),RS_INVALID);
  293. getregisterinline(list,pos,subreg,helpreg);
  294. result:=true;
  295. op:=A_MOV;
  296. hopsize:=opsize; {Save old value...}
  297. if (opcode=A_MOVZX) or (opcode=A_MOVSX) or (opcode=A_LEA) then
  298. begin
  299. {Because 'movzx memory,register' does not exist...}
  300. op:=opcode;
  301. opcode:=A_MOV;
  302. opsize:=reg2opsize(oper[1]^.reg);
  303. end;
  304. helpins:=Taicpu.op_ref_reg(op,hopsize,oper[0]^.ref^,helpreg);
  305. if pos=nil then
  306. list.insertafter(helpins,list.first)
  307. else
  308. list.insertafter(helpins,pos.next);
  309. dispose(oper[0]^.ref);
  310. oper[0]^.typ:=top_reg;
  311. oper[0]^.reg:=helpreg;
  312. oper[1]^.typ:=top_ref;
  313. new(oper[1]^.ref);
  314. oper[1]^.ref^:=spilltemplist[supreg];
  315. ungetregisterinline(list,helpins,helpreg);
  316. forward_allocation(Tai(helpins.next),instr);
  317. end
  318. else
  319. begin
  320. {Situation example:
  321. add r20d,r21d ; r20d must be spilled into [ebp-12]
  322. Change into:
  323. add [ebp-12],r21d ; Replace register by reference }
  324. if (opcode=A_MOVZX) or (opcode=A_MOVSX) then
  325. begin
  326. {Because 'movzx memory,register' does not exist...}
  327. result:=true;
  328. op:=opcode;
  329. hopsize:=opsize;
  330. opcode:=A_MOV;
  331. opsize:=reg2opsize(oper[1]^.reg);
  332. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),RS_INVALID,RS_INVALID);
  333. getregisterinline(list,pos,subreg,helpreg);
  334. helpins:=Taicpu.op_reg_reg(op,hopsize,oper[0]^.reg,helpreg);
  335. if pos=nil then
  336. list.insertafter(helpins,list.first)
  337. else
  338. list.insertafter(helpins,pos.next);
  339. oper[0]^.reg:=helpreg;
  340. ungetregisterinline(list,helpins,helpreg);
  341. forward_allocation(Tai(helpins.next),instr);
  342. end;
  343. oper[1]^.typ:=top_ref;
  344. new(oper[1]^.ref);
  345. oper[1]^.ref^:=spilltemplist[supreg];
  346. end;
  347. end;
  348. end;
  349. { The i386 instruction set never gets boring...
  350. some opcodes do not support a memory location as destination }
  351. if (oper[1]^.typ=top_ref) and
  352. (
  353. (oper[0]^.typ=top_const) or
  354. ((oper[0]^.typ=top_reg) and
  355. (getregtype(oper[0]^.reg)=regtype))
  356. ) then
  357. begin
  358. case opcode of
  359. A_IMUL :
  360. begin
  361. {Yikes! We just changed the destination register into
  362. a memory location above here.
  363. Situation examples:
  364. imul [ebp-12],r21d ; We need a help register
  365. imul [ebp-12],<const> ; We need a help register
  366. Change into:
  367. mov r22d,[ebp-12] ; Use a help instruction (only for IMUL)
  368. imul r22d,r21d ; Replace reference by helpregister
  369. mov [ebp-12],r22d ; Use another help instruction}
  370. getregisterinline(list,Tai(previous),subreg,helpreg);
  371. result:=true;
  372. {First help instruction.}
  373. helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[1]^.ref^,helpreg);
  374. if previous=nil then
  375. list.insert(helpins)
  376. else
  377. list.insertafter(helpins,previous);
  378. {Second help instruction.}
  379. helpins:=Taicpu.op_reg_ref(A_MOV,opsize,helpreg,oper[1]^.ref^);
  380. dispose(oper[1]^.ref);
  381. oper[1]^.typ:=top_reg;
  382. oper[1]^.reg:=helpreg;
  383. list.insertafter(helpins,instr);
  384. ungetregisterinline(list,instr,helpreg);
  385. end;
  386. end;
  387. end;
  388. { The i386 instruction set never gets boring...
  389. some opcodes do not support a memory location as source }
  390. if (oper[0]^.typ=top_ref) and
  391. (oper[1]^.typ=top_reg) and
  392. (getregtype(oper[1]^.reg)=regtype) then
  393. begin
  394. case opcode of
  395. A_BT,A_BTS,
  396. A_BTC,A_BTR :
  397. begin
  398. {Yikes! We just changed the source register into
  399. a memory location above here.
  400. Situation example:
  401. bt r21d,[ebp-12] ; We need a help register
  402. Change into:
  403. mov r22d,[ebp-12] ; Use a help instruction (only for IMUL)
  404. bt r21d,r22d ; Replace reference by helpregister}
  405. getregisterinline(list,Tai(previous),subreg,helpreg);
  406. result:=true;
  407. {First help instruction.}
  408. helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[0]^.ref^,helpreg);
  409. if previous=nil then
  410. list.insert(helpins)
  411. else
  412. list.insertafter(helpins,previous);
  413. dispose(oper[0]^.ref);
  414. oper[0]^.typ:=top_reg;
  415. oper[0]^.reg:=helpreg;
  416. ungetregisterinline(list,helpins,helpreg);
  417. end;
  418. end;
  419. end;
  420. end;
  421. 3:
  422. begin
  423. {$warning todo!!}
  424. end;
  425. end;
  426. end;
  427. end;
  428. {******************************************************************************
  429. Trgx86fpu
  430. ******************************************************************************}
  431. constructor Trgx86fpu.create;
  432. var i:Tsuperregister;
  433. begin
  434. used_in_proc:=[];
  435. t_times := 0;
  436. unusedregsfpu:=usableregsfpu;
  437. end;
  438. function trgx86fpu.getregisterfpu(list: taasmoutput) : tregister;
  439. begin
  440. { note: don't return R_ST0, see comments above implementation of }
  441. { a_loadfpu_* methods in cgcpu (JM) }
  442. result:=NR_ST;
  443. end;
  444. procedure trgx86fpu.ungetregisterfpu(list : taasmoutput; r : tregister);
  445. begin
  446. { nothing to do, fpu stack management is handled by the load/ }
  447. { store operations in cgcpu (JM) }
  448. end;
  449. function trgx86fpu.correct_fpuregister(r : tregister;ofs : byte) : tregister;
  450. begin
  451. correct_fpuregister:=r;
  452. setsupreg(correct_fpuregister,ofs);
  453. end;
  454. procedure trgx86fpu.saveusedfpuregisters(list: taasmoutput;
  455. var saved : tpushedsavedfpu;
  456. const s: tcpuregisterset);
  457. var
  458. r : tregister;
  459. hr : treference;
  460. begin
  461. used_in_proc:=used_in_proc+s;
  462. {$warning TODO firstsavefpureg}
  463. (*
  464. { don't try to save the fpu registers if not desired (e.g. for }
  465. { the 80x86) }
  466. if firstsavefpureg <> R_NO then
  467. for r.enum:=firstsavefpureg to lastsavefpureg do
  468. begin
  469. saved[r.enum].ofs:=reg_not_saved;
  470. { if the register is used by the calling subroutine and if }
  471. { it's not a regvar (those are handled separately) }
  472. if not is_reg_var_other[r.enum] and
  473. (r.enum in s) and
  474. { and is present in use }
  475. not(r.enum in unusedregsfpu) then
  476. begin
  477. { then save it }
  478. tg.GetTemp(list,extended_size,tt_persistent,hr);
  479. saved[r.enum].ofs:=hr.offset;
  480. cg.a_loadfpu_reg_ref(list,OS_FLOAT,r,hr);
  481. cg.a_reg_dealloc(list,r);
  482. include(unusedregsfpu,r.enum);
  483. inc(countunusedregsfpu);
  484. end;
  485. end;
  486. *)
  487. end;
  488. procedure trgx86fpu.restoreusedfpuregisters(list : taasmoutput;
  489. const saved : tpushedsavedfpu);
  490. var
  491. r,r2 : tregister;
  492. hr : treference;
  493. begin
  494. {$warning TODO firstsavefpureg}
  495. (*
  496. if firstsavefpureg <> R_NO then
  497. for r.enum:=lastsavefpureg downto firstsavefpureg do
  498. begin
  499. if saved[r.enum].ofs <> reg_not_saved then
  500. begin
  501. r2.enum:=R_INTREGISTER;
  502. r2.number:=NR_FRAME_POINTER_REG;
  503. reference_reset_base(hr,r2,saved[r.enum].ofs);
  504. cg.a_reg_alloc(list,r);
  505. cg.a_loadfpu_ref_reg(list,OS_FLOAT,hr,r);
  506. if not (r.enum in unusedregsfpu) then
  507. { internalerror(10)
  508. in n386cal we always save/restore the reg *state*
  509. using save/restoreunusedstate -> the current state
  510. may not be real (JM) }
  511. else
  512. begin
  513. dec(countunusedregsfpu);
  514. exclude(unusedregsfpu,r.enum);
  515. end;
  516. tg.UnGetTemp(list,hr);
  517. end;
  518. end;
  519. *)
  520. end;
  521. (*
  522. procedure Trgx86fpu.saveotherregvars(list: taasmoutput; const s: totherregisterset);
  523. var
  524. r: Tregister;
  525. begin
  526. if not(cs_regvars in aktglobalswitches) then
  527. exit;
  528. if firstsavefpureg <> NR_NO then
  529. for r.enum := firstsavefpureg to lastsavefpureg do
  530. if is_reg_var_other[r.enum] and
  531. (r.enum in s) then
  532. store_regvar(list,r);
  533. end;
  534. *)
  535. end.
  536. {
  537. $Log$
  538. Revision 1.2 2004-01-12 16:37:59 peter
  539. * moved spilling code from taicpu to rg
  540. Revision 1.1 2003/12/24 00:12:57 florian
  541. * rg unified for i386/x86-64
  542. Revision 1.40 2003/10/17 15:08:34 peter
  543. * commented out more obsolete constants
  544. Revision 1.39 2003/10/17 14:38:32 peter
  545. * 64k registers supported
  546. * fixed some memory leaks
  547. Revision 1.38 2003/10/10 17:48:14 peter
  548. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  549. * tregisteralloctor renamed to trgobj
  550. * removed rgobj from a lot of units
  551. * moved location_* and reference_* to cgobj
  552. * first things for mmx register allocation
  553. Revision 1.37 2003/10/09 21:31:37 daniel
  554. * Register allocator splitted, ans abstract now
  555. Revision 1.36 2003/10/01 20:34:49 peter
  556. * procinfo unit contains tprocinfo
  557. * cginfo renamed to cgbase
  558. * moved cgmessage to verbose
  559. * fixed ppc and sparc compiles
  560. Revision 1.35 2003/09/11 11:55:00 florian
  561. * improved arm code generation
  562. * move some protected and private field around
  563. * the temp. register for register parameters/arguments are now released
  564. before the move to the parameter register is done. This improves
  565. the code in a lot of cases.
  566. Revision 1.34 2003/09/09 20:59:27 daniel
  567. * Adding register allocation order
  568. Revision 1.33 2003/09/07 22:09:35 peter
  569. * preparations for different default calling conventions
  570. * various RA fixes
  571. Revision 1.32 2003/09/03 15:55:01 peter
  572. * NEWRA branch merged
  573. Revision 1.31.2.3 2003/08/31 13:50:16 daniel
  574. * Remove sorting and use pregenerated indexes
  575. * Some work on making things compile
  576. Revision 1.31.2.2 2003/08/28 18:35:08 peter
  577. * tregister changed to cardinal
  578. Revision 1.31.2.1 2003/08/27 19:55:54 peter
  579. * first tregister patch
  580. Revision 1.31 2003/08/20 09:07:00 daniel
  581. * New register coding now mandatory, some more convert_registers calls
  582. removed.
  583. Revision 1.30 2003/08/17 08:48:02 daniel
  584. * Another register allocator bug fixed.
  585. * cpu_registers set to 6 for i386
  586. Revision 1.29 2003/06/17 16:51:30 peter
  587. * cycle fixes
  588. Revision 1.28 2003/06/17 16:34:44 jonas
  589. * lots of newra fixes (need getfuncretparaloc implementation for i386)!
  590. * renamed all_intregisters to volatile_intregisters and made it
  591. processor dependent
  592. Revision 1.27 2003/06/13 21:19:31 peter
  593. * current_procdef removed, use current_procinfo.procdef instead
  594. Revision 1.26 2003/06/12 21:12:20 peter
  595. * size para for ungetregisterfpu
  596. Revision 1.25 2003/06/03 21:11:09 peter
  597. * cg.a_load_* get a from and to size specifier
  598. * makeregsize only accepts newregister
  599. * i386 uses generic tcgnotnode,tcgunaryminus
  600. Revision 1.24 2003/06/03 13:01:59 daniel
  601. * Register allocator finished
  602. Revision 1.23 2003/06/01 21:38:06 peter
  603. * getregisterfpu size parameter added
  604. * op_const_reg size parameter added
  605. * sparc updates
  606. Revision 1.22 2003/05/16 14:33:31 peter
  607. * regvar fixes
  608. Revision 1.21 2003/04/25 08:25:26 daniel
  609. * Ifdefs around a lot of calls to cleartempgen
  610. * Fixed registers that are allocated but not freed in several nodes
  611. * Tweak to register allocator to cause less spills
  612. * 8-bit registers now interfere with esi,edi and ebp
  613. Compiler can now compile rtl successfully when using new register
  614. allocator
  615. Revision 1.20 2003/04/23 14:42:08 daniel
  616. * Further register allocator work. Compiler now smaller with new
  617. allocator than without.
  618. * Somebody forgot to adjust ppu version number
  619. Revision 1.19 2003/04/22 10:09:35 daniel
  620. + Implemented the actual register allocator
  621. + Scratch registers unavailable when new register allocator used
  622. + maybe_save/maybe_restore unavailable when new register allocator used
  623. Revision 1.18 2003/04/21 19:16:50 peter
  624. * count address regs separate
  625. Revision 1.17 2003/03/28 19:16:57 peter
  626. * generic constructor working for i386
  627. * remove fixed self register
  628. * esi added as address register for i386
  629. Revision 1.16 2003/03/17 15:52:57 peter
  630. * SUPPORT_MMX define compile fix
  631. Revision 1.15 2003/03/08 13:59:17 daniel
  632. * Work to handle new register notation in ag386nsm
  633. + Added newra version of Ti386moddivnode
  634. Revision 1.14 2003/03/08 08:59:07 daniel
  635. + $define newra will enable new register allocator
  636. + getregisterint will return imaginary registers with $newra
  637. + -sr switch added, will skip register allocation so you can see
  638. the direct output of the code generator before register allocation
  639. Revision 1.13 2003/03/07 21:57:53 daniel
  640. * Improved getregisterint
  641. Revision 1.12 2003/02/19 22:00:16 daniel
  642. * Code generator converted to new register notation
  643. - Horribily outdated todo.txt removed
  644. Revision 1.11 2003/01/08 18:43:57 daniel
  645. * Tregister changed into a record
  646. Revision 1.10 2002/10/05 12:43:29 carl
  647. * fixes for Delphi 6 compilation
  648. (warning : Some features do not work under Delphi)
  649. Revision 1.9 2002/08/17 09:23:48 florian
  650. * first part of procinfo rewrite
  651. Revision 1.8 2002/07/01 18:46:34 peter
  652. * internal linker
  653. * reorganized aasm layer
  654. Revision 1.7 2002/05/16 19:46:52 carl
  655. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  656. + try to fix temp allocation (still in ifdef)
  657. + generic constructor calls
  658. + start of tassembler / tmodulebase class cleanup
  659. Revision 1.6 2002/05/12 16:53:18 peter
  660. * moved entry and exitcode to ncgutil and cgobj
  661. * foreach gets extra argument for passing local data to the
  662. iterator function
  663. * -CR checks also class typecasts at runtime by changing them
  664. into as
  665. * fixed compiler to cycle with the -CR option
  666. * fixed stabs with elf writer, finally the global variables can
  667. be watched
  668. * removed a lot of routines from cga unit and replaced them by
  669. calls to cgobj
  670. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  671. u32bit then the other is typecasted also to u32bit without giving
  672. a rangecheck warning/error.
  673. * fixed pascal calling method with reversing also the high tree in
  674. the parast, detected by tcalcst3 test
  675. Revision 1.5 2002/04/21 15:43:32 carl
  676. * changeregsize -> rg.makeregsize
  677. * changeregsize moved from cpubase to here
  678. Revision 1.4 2002/04/15 19:44:22 peter
  679. * fixed stackcheck that would be called recursively when a stack
  680. error was found
  681. * generic changeregsize(reg,size) for i386 register resizing
  682. * removed some more routines from cga unit
  683. * fixed returnvalue handling
  684. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  685. Revision 1.3 2002/04/04 19:06:13 peter
  686. * removed unused units
  687. * use tlocation.size in cg.a_*loc*() routines
  688. Revision 1.2 2002/04/02 17:11:39 peter
  689. * tlocation,treference update
  690. * LOC_CONSTANT added for better constant handling
  691. * secondadd splitted in multiple routines
  692. * location_force_reg added for loading a location to a register
  693. of a specified size
  694. * secondassignment parses now first the right and then the left node
  695. (this is compatible with Kylix). This saves a lot of push/pop especially
  696. with string operations
  697. * adapted some routines to use the new cg methods
  698. Revision 1.1 2002/03/31 20:26:40 jonas
  699. + a_loadfpu_* and a_loadmm_* methods in tcg
  700. * register allocation is now handled by a class and is mostly processor
  701. independent (+rgobj.pas and i386/rgcpu.pas)
  702. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  703. * some small improvements and fixes to the optimizer
  704. * some register allocation fixes
  705. * some fpuvaroffset fixes in the unary minus node
  706. * push/popusedregisters is now called rg.save/restoreusedregisters and
  707. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  708. also better optimizable)
  709. * fixed and optimized register saving/restoring for new/dispose nodes
  710. * LOC_FPU locations now also require their "register" field to be set to
  711. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  712. - list field removed of the tnode class because it's not used currently
  713. and can cause hard-to-find bugs
  714. }