rgx86.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  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,aasmcpu,
  26. cclasses,globtype,cgbase,rgobj;
  27. type
  28. trgx86 = class(trgobj)
  29. function get_spill_subreg(r : tregister) : tsubregister;override;
  30. function do_spill_replace(list:Taasmoutput;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;override;
  31. end;
  32. tpushedsavedloc = record
  33. case byte of
  34. 0: (pushed: boolean);
  35. 1: (ofs: longint);
  36. end;
  37. tpushedsavedfpu = array[tsuperregister] of tpushedsavedloc;
  38. trgx86fpu = class
  39. { The "usableregsxxx" contain all registers of type "xxx" that }
  40. { aren't currently allocated to a regvar. The "unusedregsxxx" }
  41. { contain all registers of type "xxx" that aren't currently }
  42. { allocated }
  43. unusedregsfpu,usableregsfpu : Tsuperregisterset;
  44. { these counters contain the number of elements in the }
  45. { unusedregsxxx/usableregsxxx sets }
  46. countunusedregsfpu : byte;
  47. { Contains the registers which are really used by the proc itself.
  48. It doesn't take care of registers used by called procedures
  49. }
  50. used_in_proc : tcpuregisterset;
  51. {reg_pushes_other : regvarother_longintarray;
  52. is_reg_var_other : regvarother_booleanarray;
  53. regvar_loaded_other : regvarother_booleanarray;}
  54. { tries to hold the amount of times which the current tree is processed }
  55. t_times: longint;
  56. fpuvaroffset : byte;
  57. constructor create;
  58. function getregisterfpu(list: taasmoutput) : tregister;
  59. procedure ungetregisterfpu(list: taasmoutput; r : tregister);
  60. { pushes and restores registers }
  61. procedure saveusedfpuregisters(list:Taasmoutput;
  62. var saved:Tpushedsavedfpu;
  63. const s:Tcpuregisterset);
  64. procedure restoreusedfpuregisters(list:Taasmoutput;
  65. const saved:Tpushedsavedfpu);
  66. { corrects the fpu stack register by ofs }
  67. function correct_fpuregister(r : tregister;ofs : byte) : tregister;
  68. end;
  69. implementation
  70. uses
  71. systems,
  72. verbose;
  73. const
  74. { This value is used in tsaved. If the array value is equal
  75. to this, then this means that this register is not used.}
  76. reg_not_saved = $7fffffff;
  77. {******************************************************************************
  78. Trgcpu
  79. ******************************************************************************}
  80. {$ifdef OLDRGX86}
  81. function trgx86.instr_spill_register(list:Taasmoutput;
  82. instr:taicpu;
  83. const r:Tsuperregisterset;
  84. const spilltemplist:Tspill_temp_list): boolean;
  85. {
  86. Spill the registers in r in this instruction. Returns true if any help
  87. registers are used. This procedure has become one big hack party, because
  88. of the huge amount of situations you can have. The irregularity of the i386
  89. instruction set doesn't help either. (DM)
  90. }
  91. var i:byte;
  92. supreg:Tsuperregister;
  93. subreg:Tsubregister;
  94. helpreg:Tregister;
  95. helpins:Taicpu;
  96. op:Tasmop;
  97. hopsize:Topsize;
  98. pos:Tai;
  99. begin
  100. {Situation examples are in intel notation, so operand order:
  101. mov eax , ebx
  102. ^^^ ^^^
  103. oper[1] oper[0]
  104. (DM)}
  105. result:=false;
  106. with taicpu(instr) do
  107. begin
  108. case ops of
  109. 0:
  110. ;
  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. 3 :
  184. begin
  185. { Opcodes with 3 registers are shrd/shld, where the 3rd operand is const or CL,
  186. that doesn't need spilling }
  187. { First spill the registers from the references. This is
  188. required because the reference can be moved from this instruction
  189. to a MOV instruction when spilling of the register operand is done }
  190. for i:=0 to 1 do
  191. if oper[i]^.typ=top_ref then
  192. begin
  193. supreg:=getsupreg(oper[i]^.ref^.base);
  194. if supregset_in(r,supreg) then
  195. begin
  196. {Situation example:
  197. add r20d,[r21d+4*r22d] ; r21d must be spilled into [ebp-12]
  198. Change into:
  199. mov r23d,[ebp-12] ; Use a help register
  200. add r20d,[r23d+4*r22d] ; Replace register by helpregister }
  201. subreg:=getsubreg(oper[i]^.ref^.base);
  202. if i=1 then
  203. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),getsupreg(oper[0]^.reg),RS_INVALID)
  204. else
  205. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),RS_INVALID,RS_INVALID);
  206. getregisterinline(list,pos,subreg,helpreg);
  207. result:=true;
  208. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.base),spilltemplist[supreg],helpreg);
  209. if pos=nil then
  210. list.insertafter(helpins,list.first)
  211. else
  212. list.insertafter(helpins,pos.next);
  213. oper[i]^.ref^.base:=helpreg;
  214. ungetregisterinline(list,helpins,helpreg);
  215. forward_allocation(Tai(helpins.next),instr);
  216. end;
  217. supreg:=getsupreg(oper[i]^.ref^.index);
  218. if supregset_in(r,supreg) then
  219. begin
  220. {Situation example:
  221. add r20d,[r21d+4*r22d] ; r22d must be spilled into [ebp-12]
  222. Change into:
  223. mov r23d,[ebp-12] ; Use a help register
  224. add r20d,[r21d+4*r23d] ; Replace register by helpregister }
  225. subreg:=getsubreg(oper[i]^.ref^.index);
  226. if i=1 then
  227. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),
  228. getsupreg(oper[0]^.reg),RS_INVALID)
  229. else
  230. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),RS_INVALID,RS_INVALID);
  231. getregisterinline(list,pos,subreg,helpreg);
  232. result:=true;
  233. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.index),spilltemplist[supreg],helpreg);
  234. if pos=nil then
  235. list.insertafter(helpins,list.first)
  236. else
  237. list.insertafter(helpins,pos.next);
  238. oper[i]^.ref^.index:=helpreg;
  239. ungetregisterinline(list,helpins,helpreg);
  240. forward_allocation(Tai(helpins.next),instr);
  241. end;
  242. end;
  243. if (oper[0]^.typ=top_reg) and
  244. (getregtype(oper[0]^.reg)=regtype) then
  245. begin
  246. supreg:=getsupreg(oper[0]^.reg);
  247. subreg:=getsubreg(oper[0]^.reg);
  248. if supregset_in(r,supreg) then
  249. if oper[1]^.typ=top_ref then
  250. begin
  251. {Situation example:
  252. add [r20d],r21d ; r21d must be spilled into [ebp-12]
  253. Change into:
  254. mov r22d,[ebp-12] ; Use a help register
  255. add [r20d],r22d ; Replace register by helpregister }
  256. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),
  257. getsupreg(oper[1]^.ref^.base),getsupreg(oper[1]^.ref^.index));
  258. getregisterinline(list,pos,subreg,helpreg);
  259. result:=true;
  260. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.reg),spilltemplist[supreg],helpreg);
  261. if pos=nil then
  262. list.insertafter(helpins,list.first)
  263. else
  264. list.insertafter(helpins,pos.next);
  265. oper[0]^.reg:=helpreg;
  266. ungetregisterinline(list,helpins,helpreg);
  267. forward_allocation(Tai(helpins.next),instr);
  268. end
  269. else
  270. begin
  271. {Situation example:
  272. add r20d,r21d ; r21d must be spilled into [ebp-12]
  273. Change into:
  274. add r20d,[ebp-12] ; Replace register by reference }
  275. oper[0]^.typ:=top_ref;
  276. new(oper[0]^.ref);
  277. oper[0]^.ref^:=spilltemplist[supreg];
  278. end;
  279. end;
  280. if (oper[1]^.typ=top_reg) and
  281. (getregtype(oper[1]^.reg)=regtype) then
  282. begin
  283. supreg:=getsupreg(oper[1]^.reg);
  284. subreg:=getsubreg(oper[1]^.reg);
  285. if supregset_in(r,supreg) then
  286. begin
  287. if oper[0]^.typ=top_ref then
  288. begin
  289. {Situation example:
  290. add r20d,[r21d] ; r20d must be spilled into [ebp-12]
  291. Change into:
  292. mov r22d,[r21d] ; Use a help register
  293. add [ebp-12],r22d ; Replace register by helpregister }
  294. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),
  295. getsupreg(oper[0]^.ref^.index),RS_INVALID);
  296. getregisterinline(list,pos,subreg,helpreg);
  297. result:=true;
  298. op:=A_MOV;
  299. hopsize:=opsize; {Save old value...}
  300. if (opcode=A_MOVZX) or (opcode=A_MOVSX) or (opcode=A_LEA) then
  301. begin
  302. {Because 'movzx memory,register' does not exist...}
  303. op:=opcode;
  304. opcode:=A_MOV;
  305. opsize:=reg2opsize(oper[1]^.reg);
  306. end;
  307. helpins:=Taicpu.op_ref_reg(op,hopsize,oper[0]^.ref^,helpreg);
  308. if pos=nil then
  309. list.insertafter(helpins,list.first)
  310. else
  311. list.insertafter(helpins,pos.next);
  312. dispose(oper[0]^.ref);
  313. oper[0]^.typ:=top_reg;
  314. oper[0]^.reg:=helpreg;
  315. oper[1]^.typ:=top_ref;
  316. new(oper[1]^.ref);
  317. oper[1]^.ref^:=spilltemplist[supreg];
  318. ungetregisterinline(list,helpins,helpreg);
  319. forward_allocation(Tai(helpins.next),instr);
  320. end
  321. else
  322. begin
  323. {Situation example:
  324. add r20d,r21d ; r20d must be spilled into [ebp-12]
  325. Change into:
  326. add [ebp-12],r21d ; Replace register by reference }
  327. if (opcode=A_MOVZX) or (opcode=A_MOVSX) then
  328. begin
  329. {Because 'movzx memory,register' does not exist...}
  330. result:=true;
  331. op:=opcode;
  332. hopsize:=opsize;
  333. opcode:=A_MOV;
  334. opsize:=reg2opsize(oper[1]^.reg);
  335. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),RS_INVALID,RS_INVALID);
  336. getregisterinline(list,pos,subreg,helpreg);
  337. helpins:=Taicpu.op_reg_reg(op,hopsize,oper[0]^.reg,helpreg);
  338. if pos=nil then
  339. list.insertafter(helpins,list.first)
  340. else
  341. list.insertafter(helpins,pos.next);
  342. oper[0]^.reg:=helpreg;
  343. ungetregisterinline(list,helpins,helpreg);
  344. forward_allocation(Tai(helpins.next),instr);
  345. end;
  346. oper[1]^.typ:=top_ref;
  347. new(oper[1]^.ref);
  348. oper[1]^.ref^:=spilltemplist[supreg];
  349. end;
  350. end;
  351. end;
  352. { The i386 instruction set never gets boring...
  353. some opcodes do not support a memory location as destination }
  354. if (oper[1]^.typ=top_ref) and
  355. (
  356. (oper[0]^.typ=top_const) or
  357. ((oper[0]^.typ=top_reg) and
  358. (getregtype(oper[0]^.reg)=regtype))
  359. ) then
  360. begin
  361. case opcode of
  362. A_SHLD,A_SHRD,
  363. A_IMUL :
  364. begin
  365. {Yikes! We just changed the destination register into
  366. a memory location above here.
  367. Situation examples:
  368. imul [ebp-12],r21d ; We need a help register
  369. imul [ebp-12],<const> ; We need a help register
  370. Change into:
  371. mov r22d,[ebp-12] ; Use a help instruction (only for IMUL)
  372. imul r22d,r21d ; Replace reference by helpregister
  373. mov [ebp-12],r22d ; Use another help instruction}
  374. getregisterinline(list,Tai(previous),subreg,helpreg);
  375. result:=true;
  376. {First help instruction.}
  377. helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[1]^.ref^,helpreg);
  378. if previous=nil then
  379. list.insert(helpins)
  380. else
  381. list.insertafter(helpins,previous);
  382. {Second help instruction.}
  383. helpins:=Taicpu.op_reg_ref(A_MOV,opsize,helpreg,oper[1]^.ref^);
  384. dispose(oper[1]^.ref);
  385. oper[1]^.typ:=top_reg;
  386. oper[1]^.reg:=helpreg;
  387. list.insertafter(helpins,instr);
  388. ungetregisterinline(list,instr,helpreg);
  389. end;
  390. end;
  391. end;
  392. { The i386 instruction set never gets boring...
  393. some opcodes do not support a memory location as source }
  394. if (oper[0]^.typ=top_ref) and
  395. (oper[1]^.typ=top_reg) and
  396. (getregtype(oper[1]^.reg)=regtype) then
  397. begin
  398. case opcode of
  399. A_BT,A_BTS,
  400. A_BTC,A_BTR :
  401. begin
  402. {Yikes! We just changed the source register into
  403. a memory location above here.
  404. Situation example:
  405. bt r21d,[ebp-12] ; We need a help register
  406. Change into:
  407. mov r22d,[ebp-12] ; Use a help instruction (only for IMUL)
  408. bt r21d,r22d ; Replace reference by helpregister}
  409. getregisterinline(list,Tai(previous),subreg,helpreg);
  410. result:=true;
  411. {First help instruction.}
  412. helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[0]^.ref^,helpreg);
  413. if previous=nil then
  414. list.insert(helpins)
  415. else
  416. list.insertafter(helpins,previous);
  417. dispose(oper[0]^.ref);
  418. oper[0]^.typ:=top_reg;
  419. oper[0]^.reg:=helpreg;
  420. ungetregisterinline(list,helpins,helpreg);
  421. end;
  422. end;
  423. end;
  424. end;
  425. else
  426. internalerror(200409202);
  427. end;
  428. end;
  429. end;
  430. {$endif OLDRGX86}
  431. function trgx86.get_spill_subreg(r : tregister) : tsubregister;
  432. begin
  433. result:=getsubreg(r);
  434. end;
  435. function trgx86.do_spill_replace(list:Taasmoutput;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
  436. begin
  437. result:=false;
  438. end;
  439. {******************************************************************************
  440. Trgx86fpu
  441. ******************************************************************************}
  442. constructor Trgx86fpu.create;
  443. begin
  444. used_in_proc:=[];
  445. t_times := 0;
  446. unusedregsfpu:=usableregsfpu;
  447. end;
  448. function trgx86fpu.getregisterfpu(list: taasmoutput) : tregister;
  449. begin
  450. { note: don't return R_ST0, see comments above implementation of }
  451. { a_loadfpu_* methods in cgcpu (JM) }
  452. result:=NR_ST;
  453. end;
  454. procedure trgx86fpu.ungetregisterfpu(list : taasmoutput; r : tregister);
  455. begin
  456. { nothing to do, fpu stack management is handled by the load/ }
  457. { store operations in cgcpu (JM) }
  458. end;
  459. function trgx86fpu.correct_fpuregister(r : tregister;ofs : byte) : tregister;
  460. begin
  461. correct_fpuregister:=r;
  462. setsupreg(correct_fpuregister,ofs);
  463. end;
  464. procedure trgx86fpu.saveusedfpuregisters(list: taasmoutput;
  465. var saved : tpushedsavedfpu;
  466. const s: tcpuregisterset);
  467. var
  468. r : tregister;
  469. hr : treference;
  470. begin
  471. used_in_proc:=used_in_proc+s;
  472. {$warning TODO firstsavefpureg}
  473. (*
  474. { don't try to save the fpu registers if not desired (e.g. for }
  475. { the 80x86) }
  476. if firstsavefpureg <> R_NO then
  477. for r.enum:=firstsavefpureg to lastsavefpureg do
  478. begin
  479. saved[r.enum].ofs:=reg_not_saved;
  480. { if the register is used by the calling subroutine and if }
  481. { it's not a regvar (those are handled separately) }
  482. if not is_reg_var_other[r.enum] and
  483. (r.enum in s) and
  484. { and is present in use }
  485. not(r.enum in unusedregsfpu) then
  486. begin
  487. { then save it }
  488. tg.GetTemp(list,extended_size,tt_persistent,hr);
  489. saved[r.enum].ofs:=hr.offset;
  490. cg.a_loadfpu_reg_ref(list,OS_FLOAT,r,hr);
  491. cg.a_reg_dealloc(list,r);
  492. include(unusedregsfpu,r.enum);
  493. inc(countunusedregsfpu);
  494. end;
  495. end;
  496. *)
  497. end;
  498. procedure trgx86fpu.restoreusedfpuregisters(list : taasmoutput;
  499. const saved : tpushedsavedfpu);
  500. var
  501. r,r2 : tregister;
  502. hr : treference;
  503. begin
  504. {$warning TODO firstsavefpureg}
  505. (*
  506. if firstsavefpureg <> R_NO then
  507. for r.enum:=lastsavefpureg downto firstsavefpureg do
  508. begin
  509. if saved[r.enum].ofs <> reg_not_saved then
  510. begin
  511. r2.enum:=R_INTREGISTER;
  512. r2.number:=NR_FRAME_POINTER_REG;
  513. reference_reset_base(hr,r2,saved[r.enum].ofs);
  514. cg.a_reg_alloc(list,r);
  515. cg.a_loadfpu_ref_reg(list,OS_FLOAT,hr,r);
  516. if not (r.enum in unusedregsfpu) then
  517. { internalerror(10)
  518. in n386cal we always save/restore the reg *state*
  519. using save/restoreunusedstate -> the current state
  520. may not be real (JM) }
  521. else
  522. begin
  523. dec(countunusedregsfpu);
  524. exclude(unusedregsfpu,r.enum);
  525. end;
  526. tg.UnGetTemp(list,hr);
  527. end;
  528. end;
  529. *)
  530. end;
  531. (*
  532. procedure Trgx86fpu.saveotherregvars(list: taasmoutput; const s: totherregisterset);
  533. var
  534. r: Tregister;
  535. begin
  536. if not(cs_regvars in aktglobalswitches) then
  537. exit;
  538. if firstsavefpureg <> NR_NO then
  539. for r.enum := firstsavefpureg to lastsavefpureg do
  540. if is_reg_var_other[r.enum] and
  541. (r.enum in s) then
  542. store_regvar(list,r);
  543. end;
  544. *)
  545. end.
  546. {
  547. $Log$
  548. Revision 1.8 2004-10-05 20:41:02 peter
  549. * more spilling rewrites
  550. Revision 1.7 2004/10/04 20:46:22 peter
  551. * spilling code rewritten for x86. It now used the generic
  552. spilling routines. Special x86 optimization still needs
  553. to be added.
  554. * Spilling fixed when both operands needed to be spilled
  555. * Cleanup of spilling routine, do_spill_readwritten removed
  556. Revision 1.6 2004/09/27 14:49:45 peter
  557. * handle 3 operand opcodes the same as 2 operand opcodes, the
  558. third operand can only be a const or register CL, so it doesn't
  559. affect spilling
  560. * support shrd/shld that don't allow memory operands
  561. Revision 1.5 2004/09/26 07:15:07 florian
  562. * ie checking in spilling code improved
  563. Revision 1.4 2004/06/20 08:55:32 florian
  564. * logs truncated
  565. Revision 1.3 2004/06/16 20:07:11 florian
  566. * dwarf branch merged
  567. Revision 1.2.2.1 2004/04/10 12:36:42 peter
  568. * fixed alignment issues
  569. Revision 1.2 2004/01/12 16:37:59 peter
  570. * moved spilling code from taicpu to rg
  571. }