rgx86.pas 29 KB

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