ncgbas.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. This unit implements some basic nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ncgbas;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. aasmtai,aasmdata,
  23. cpubase,cgutils,
  24. node,nbas;
  25. type
  26. tcgnothingnode = class(tnothingnode)
  27. procedure pass_generate_code;override;
  28. end;
  29. tcgasmnode = class(tasmnode)
  30. protected
  31. procedure ResolveRef(const filepos: tfileposinfo; var op:toper); virtual;
  32. public
  33. procedure pass_generate_code;override;
  34. end;
  35. tcgstatementnode = class(tstatementnode)
  36. procedure pass_generate_code;override;
  37. end;
  38. tcgblocknode = class(tblocknode)
  39. procedure pass_generate_code;override;
  40. end;
  41. tcgtempcreatenode = class(ttempcreatenode)
  42. procedure pass_generate_code;override;
  43. end;
  44. tcgtemprefnode = class(ttemprefnode)
  45. procedure pass_generate_code;override;
  46. { Changes the location of this temp to ref. Useful when assigning }
  47. { another temp to this one. The current location will be freed. }
  48. { Can only be called in pass 2 (since earlier, the temp location }
  49. { isn't known yet) }
  50. procedure changelocation(const ref: treference);
  51. end;
  52. tcgtempdeletenode = class(ttempdeletenode)
  53. procedure pass_generate_code;override;
  54. end;
  55. implementation
  56. uses
  57. globals,
  58. cutils,verbose,
  59. aasmbase,aasmcpu,
  60. symsym,symconst,defutil,
  61. pass_2,ncgutil,
  62. cgbase,cgobj,hlcgobj,
  63. procinfo,
  64. cpuinfo,
  65. tgobj
  66. ;
  67. {*****************************************************************************
  68. TNOTHING
  69. *****************************************************************************}
  70. procedure tcgnothingnode.pass_generate_code;
  71. begin
  72. location_reset(location,LOC_VOID,OS_NO);
  73. { avoid an abstract rte }
  74. end;
  75. {*****************************************************************************
  76. TSTATEMENTNODE
  77. *****************************************************************************}
  78. procedure tcgstatementnode.pass_generate_code;
  79. var
  80. hp : tstatementnode;
  81. begin
  82. location_reset(location,LOC_VOID,OS_NO);
  83. hp:=self;
  84. while assigned(hp) do
  85. begin
  86. if assigned(hp.left) then
  87. begin
  88. secondpass(hp.left);
  89. { Compiler inserted blocks can return values }
  90. location_copy(hp.location,hp.left.location);
  91. end;
  92. hp:=tstatementnode(hp.right);
  93. end;
  94. end;
  95. {*****************************************************************************
  96. TASMNODE
  97. *****************************************************************************}
  98. procedure tcgasmnode.ResolveRef(const filepos: tfileposinfo; var op:toper);
  99. var
  100. sym : tabstractnormalvarsym;
  101. {$ifdef x86}
  102. scale : byte;
  103. {$endif x86}
  104. forceref,
  105. getoffset : boolean;
  106. indexreg : tregister;
  107. sofs : longint;
  108. begin
  109. if (op.typ=top_local) then
  110. begin
  111. sofs:=op.localoper^.localsymofs;
  112. indexreg:=op.localoper^.localindexreg;
  113. {$ifdef x86}
  114. scale:=op.localoper^.localscale;
  115. {$endif x86}
  116. getoffset:=op.localoper^.localgetoffset;
  117. forceref:=op.localoper^.localforceref;
  118. sym:=tabstractnormalvarsym(pointer(op.localoper^.localsym));
  119. dispose(op.localoper);
  120. case sym.localloc.loc of
  121. LOC_REFERENCE :
  122. begin
  123. if getoffset then
  124. begin
  125. if indexreg=NR_NO then
  126. begin
  127. op.typ:=top_const;
  128. op.val:=sym.localloc.reference.offset+sofs;
  129. end
  130. else
  131. begin
  132. op.typ:=top_ref;
  133. new(op.ref);
  134. reference_reset_base(op.ref^,indexreg,sym.localloc.reference.offset+sofs,
  135. newalignment(sym.localloc.reference.alignment,sofs),[]);
  136. end;
  137. end
  138. else
  139. begin
  140. op.typ:=top_ref;
  141. new(op.ref);
  142. reference_reset_base(op.ref^,sym.localloc.reference.base,sym.localloc.reference.offset+sofs,
  143. newalignment(sym.localloc.reference.alignment,sofs),[]);
  144. op.ref^.index:=indexreg;
  145. {$ifdef x86}
  146. op.ref^.scalefactor:=scale;
  147. {$endif x86}
  148. end;
  149. end;
  150. LOC_REGISTER :
  151. begin
  152. if getoffset then
  153. MessagePos(filepos,asmr_e_invalid_reference_syntax);
  154. { Subscribed access }
  155. if forceref or
  156. {$ifdef avr}
  157. (sofs>=tcgsize2size[sym.localloc.size])
  158. {$else avr}
  159. (sofs<>0)
  160. {$endif avr}
  161. then
  162. begin
  163. op.typ:=top_ref;
  164. new(op.ref);
  165. { no idea about the actual alignment }
  166. reference_reset_base(op.ref^,sym.localloc.register,sofs,1,[]);
  167. op.ref^.index:=indexreg;
  168. {$ifdef x86}
  169. op.ref^.scalefactor:=scale;
  170. {$endif x86}
  171. end
  172. else
  173. begin
  174. op.typ:=top_reg;
  175. op.reg:=sym.localloc.register;
  176. {$ifdef avr}
  177. case sofs of
  178. 1: op.reg:=cg.GetNextReg(op.reg);
  179. 2: op.reg:=cg.GetNextReg(cg.GetNextReg(op.reg));
  180. 3: op.reg:=cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(op.reg)));
  181. end;
  182. {$endif avr}
  183. end;
  184. end;
  185. LOC_FPUREGISTER,
  186. LOC_MMXREGISTER,
  187. LOC_MMREGISTER :
  188. begin
  189. op.typ:=top_reg;
  190. op.reg:=NR_NO;
  191. if getoffset then
  192. MessagePos(filepos,asmr_e_invalid_reference_syntax);
  193. { Using an MM/FPU register in a reference is not possible }
  194. if forceref or (sofs<>0) then
  195. MessagePos1(filepos,asmr_e_invalid_ref_register,std_regname(sym.localloc.register))
  196. else
  197. op.reg:=sym.localloc.register;
  198. end;
  199. LOC_INVALID :
  200. begin
  201. { in "assembler; nostackframe;" routines, the
  202. funcret loc is set to LOC_INVALID in case the
  203. result is returned via a complex location
  204. (more than one register, ...) }
  205. if (vo_is_funcret in tabstractvarsym(sym).varoptions) then
  206. MessagePos(filepos,asmr_e_complex_function_result_location)
  207. else
  208. internalerror(2012082101);
  209. { recover }
  210. op.typ:=top_reg;
  211. op.reg:=NR_FUNCTION_RETURN_REG;
  212. end;
  213. else
  214. internalerror(201001031);
  215. end;
  216. end;
  217. end;
  218. procedure tcgasmnode.pass_generate_code;
  219. procedure ReLabel(var p:tasmsymbol);
  220. begin
  221. { Only relabel local tasmlabels }
  222. if (p.bind = AB_LOCAL) and
  223. (p is tasmlabel) then
  224. begin
  225. if not assigned(p.altsymbol) then
  226. current_asmdata.GenerateAltSymbol(p);
  227. p:=p.altsymbol;
  228. p.increfs;
  229. end;
  230. end;
  231. var
  232. hp,hp2 : tai;
  233. i : longint;
  234. begin
  235. location_reset(location,LOC_VOID,OS_NO);
  236. if (nf_get_asm_position in flags) then
  237. begin
  238. { Add a marker, to be sure the list is not empty }
  239. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_Position));
  240. currenttai:=tai(current_asmdata.CurrAsmList.last);
  241. exit;
  242. end;
  243. { Switch to the CPU instruction set, specified by the $ASMCPU directive }
  244. current_asmdata.CurrAsmList.Concat(tai_directive.create(asd_cpu,cputypestr[current_settings.asmcputype]));
  245. { Allocate registers used in the assembler block }
  246. { has_registerlist=true means that registers are specified and already allocated }
  247. if (not has_registerlist) then
  248. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  249. if (po_inline in current_procinfo.procdef.procoptions) then
  250. begin
  251. hp:=tai(p_asm.first);
  252. while assigned(hp) do
  253. begin
  254. hp2:=tai(hp.getcopy);
  255. case hp2.typ of
  256. ait_label :
  257. ReLabel(tasmsymbol(tai_label(hp2).labsym));
  258. ait_const :
  259. begin
  260. if assigned(tai_const(hp2).sym) then
  261. ReLabel(tai_const(hp2).sym);
  262. if assigned(tai_const(hp2).endsym) then
  263. ReLabel(tai_const(hp2).endsym);
  264. end;
  265. ait_instruction :
  266. begin
  267. { remove cached insentry, because the new code can
  268. require another less optimized instruction }
  269. {$ifdef i386}
  270. {$ifndef NOAG386BIN}
  271. taicpu(hp2).ResetPass1;
  272. {$endif}
  273. {$endif}
  274. { fixup the references }
  275. for i:=1 to taicpu(hp2).ops do
  276. begin
  277. ResolveRef(taicpu(hp2).fileinfo,taicpu(hp2).oper[i-1]^);
  278. with taicpu(hp2).oper[i-1]^ do
  279. begin
  280. case typ of
  281. top_ref :
  282. begin
  283. if assigned(ref^.symbol) then
  284. ReLabel(ref^.symbol);
  285. if assigned(ref^.relsymbol) then
  286. ReLabel(ref^.relsymbol);
  287. end;
  288. end;
  289. end;
  290. end;
  291. {$ifdef x86}
  292. { can only be checked now that all local operands }
  293. { have been resolved }
  294. taicpu(hp2).CheckIfValid;
  295. {$endif x86}
  296. end;
  297. end;
  298. current_asmdata.CurrAsmList.concat(hp2);
  299. hp:=tai(hp.next);
  300. end;
  301. { restore used symbols }
  302. current_asmdata.ResetAltSymbols;
  303. end
  304. else
  305. begin
  306. hp:=tai(p_asm.first);
  307. while assigned(hp) do
  308. begin
  309. case hp.typ of
  310. ait_instruction :
  311. begin
  312. { remove cached insentry, because the new code can
  313. require another less optimized instruction }
  314. {$ifdef i386}
  315. {$ifndef NOAG386BIN}
  316. taicpu(hp).ResetPass1;
  317. {$endif}
  318. {$endif}
  319. { fixup the references }
  320. for i:=1 to taicpu(hp).ops do
  321. ResolveRef(taicpu(hp).fileinfo,taicpu(hp).oper[i-1]^);
  322. {$ifdef x86}
  323. { can only be checked now that all local operands }
  324. { have been resolved }
  325. taicpu(hp).CheckIfValid;
  326. {$endif x86}
  327. end;
  328. end;
  329. hp:=tai(hp.next);
  330. end;
  331. { insert the list }
  332. current_asmdata.CurrAsmList.concatlist(p_asm);
  333. end;
  334. { Update section count }
  335. current_asmdata.currasmlist.section_count:=current_asmdata.currasmlist.section_count+p_asm.section_count;
  336. { Release register used in the assembler block }
  337. if (not has_registerlist) then
  338. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  339. { Switch back to the CPU instruction set of the target CPU }
  340. current_asmdata.CurrAsmList.Concat(tai_directive.create(asd_cpu,cputypestr[current_settings.cputype]));
  341. end;
  342. {*****************************************************************************
  343. TBLOCKNODE
  344. *****************************************************************************}
  345. procedure tcgblocknode.pass_generate_code;
  346. var
  347. hp : tstatementnode;
  348. oldexitlabel : tasmlabel;
  349. oldflowcontrol : tflowcontrol;
  350. begin
  351. location_reset(location,LOC_VOID,OS_NO);
  352. oldflowcontrol:=[];
  353. oldexitlabel:=nil;
  354. { replace exitlabel? }
  355. if nf_block_with_exit in flags then
  356. begin
  357. oldexitlabel:=current_procinfo.CurrExitLabel;
  358. current_asmdata.getjumplabel(current_procinfo.CurrExitLabel);
  359. oldflowcontrol:=flowcontrol;
  360. { the nested block will not span an exit statement of the parent }
  361. exclude(flowcontrol,fc_exit);
  362. end;
  363. { do second pass on left node }
  364. if assigned(left) then
  365. begin
  366. hp:=tstatementnode(left);
  367. while assigned(hp) do
  368. begin
  369. if assigned(hp.left) then
  370. begin
  371. secondpass(hp.left);
  372. location_copy(hp.location,hp.left.location);
  373. end;
  374. location_copy(location,hp.location);
  375. hp:=tstatementnode(hp.right);
  376. end;
  377. end;
  378. { write exitlabel }
  379. if nf_block_with_exit in flags then
  380. begin
  381. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel);
  382. current_procinfo.CurrExitLabel:=oldexitlabel;
  383. { the exit statements inside this block are not exit statements }
  384. { out of the parent }
  385. flowcontrol:=oldflowcontrol+(flowcontrol - [fc_exit]);
  386. end;
  387. end;
  388. {*****************************************************************************
  389. TTEMPCREATENODE
  390. *****************************************************************************}
  391. procedure tcgtempcreatenode.pass_generate_code;
  392. begin
  393. location_reset(location,LOC_VOID,OS_NO);
  394. { if we're secondpassing the same tcgtempcreatenode twice, we have a bug }
  395. if (ti_valid in tempflags) then
  396. internalerror(200108222);
  397. { in case of ti_reference, the location will be initialised using the
  398. location of the tempinitnode once the first temprefnode is processed }
  399. if not(ti_reference in tempflags) then
  400. begin
  401. { get a (persistent) temp }
  402. if is_managed_type(tempinfo^.typedef) and
  403. not(ti_const in tempflags) then
  404. begin
  405. location_reset_ref(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.typedef),0,[]);
  406. tg.gethltempmanaged(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.temptype,tempinfo^.location.reference);
  407. if not(ti_nofini in tempflags) then
  408. hlcg.g_finalize(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.location.reference);
  409. end
  410. else if (ti_may_be_in_reg in tempflags) then
  411. begin
  412. location_allocate_register(current_asmdata.CurrAsmList,tempinfo^.location,tempinfo^.typedef,tempinfo^.temptype = tt_persistent);
  413. end
  414. else
  415. begin
  416. location_reset_ref(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.typedef),0,[]);
  417. tg.gethltemp(current_asmdata.CurrAsmList,tempinfo^.typedef,size,tempinfo^.temptype,tempinfo^.location.reference);
  418. end;
  419. end;
  420. includetempflag(ti_valid);
  421. if assigned(tempinfo^.tempinitcode) then
  422. includetempflag(ti_executeinitialisation);
  423. end;
  424. {*****************************************************************************
  425. TTEMPREFNODE
  426. *****************************************************************************}
  427. procedure tcgtemprefnode.pass_generate_code;
  428. begin
  429. if ti_executeinitialisation in tempflags then
  430. begin
  431. { avoid recursion }
  432. excludetempflag(ti_executeinitialisation);
  433. secondpass(tempinfo^.tempinitcode);
  434. if (ti_reference in tempflags) then
  435. begin
  436. case tempinfo^.tempinitcode.location.loc of
  437. LOC_CREGISTER,
  438. LOC_CFPUREGISTER,
  439. LOC_CMMREGISTER,
  440. LOC_CSUBSETREG:
  441. begin
  442. { although it's ok if we need this value multiple times
  443. for reading, it's not in case of writing (because the
  444. register could change due to SSA -> storing to the saved
  445. register afterwards would be wrong). }
  446. if not(ti_readonly in tempflags) then
  447. internalerror(2011031407);
  448. end;
  449. { in case reference contains CREGISTERS, that doesn't matter:
  450. we want to write to the location indicated by the current
  451. value of those registers, and we can save those values }
  452. end;
  453. hlcg.g_reference_loc(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.tempinitcode.location,tempinfo^.location);
  454. end;
  455. end;
  456. { check if the temp is valid }
  457. if not(ti_valid in tempflags) then
  458. internalerror(200108231);
  459. location:=tempinfo^.location;
  460. case tempinfo^.location.loc of
  461. LOC_REFERENCE:
  462. begin
  463. { ti_valid should be excluded if it's a normal temp }
  464. end;
  465. LOC_REGISTER,
  466. LOC_FPUREGISTER,
  467. LOC_MMREGISTER :
  468. excludetempflag(ti_valid);
  469. end;
  470. end;
  471. procedure tcgtemprefnode.changelocation(const ref: treference);
  472. begin
  473. { check if the temp is valid }
  474. if not(ti_valid in tempflags) then
  475. internalerror(200306081);
  476. if (tempinfo^.location.loc<>LOC_REFERENCE) then
  477. internalerror(2004020203);
  478. if (tempinfo^.temptype = tt_persistent) then
  479. tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tt_normal);
  480. tg.ungettemp(current_asmdata.CurrAsmList,tempinfo^.location.reference);
  481. tempinfo^.location.reference := ref;
  482. tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tempinfo^.temptype);
  483. { adapt location }
  484. location.reference := ref;
  485. end;
  486. {*****************************************************************************
  487. TTEMPDELETENODE
  488. *****************************************************************************}
  489. procedure tcgtempdeletenode.pass_generate_code;
  490. begin
  491. if ti_reference in tempflags then
  492. begin
  493. { release_to_normal means that the temp will be freed the next
  494. time it's used. However, reference temps reference some other
  495. location that is not managed by this temp and hence cannot be
  496. freed }
  497. if release_to_normal then
  498. internalerror(2011052205);
  499. { so we only mark this temp location as "no longer valid" when
  500. it's deleted (ttempdeletenodes are also used during getcopy, so
  501. we really do need one) }
  502. excludetempflag(ti_valid);
  503. exit;
  504. end;
  505. location_reset(location,LOC_VOID,OS_NO);
  506. { see comments at ti_const declaration: if we initialised this temp with
  507. the value of another temp, that other temp was not freed because the
  508. ti_const flag was set }
  509. if (ti_const in tempflags) and
  510. assigned(tempinfo^.tempinitcode) then
  511. begin
  512. if tempinfo^.tempinitcode.nodetype<>assignn then
  513. internalerror(2016081201);
  514. if tbinarynode(tempinfo^.tempinitcode).right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  515. tg.ungetiftemp(current_asmdata.CurrAsmList,tbinarynode(tempinfo^.tempinitcode).right.location.reference);
  516. end;
  517. case tempinfo^.location.loc of
  518. LOC_REFERENCE:
  519. begin
  520. if release_to_normal then
  521. tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tt_normal)
  522. else
  523. begin
  524. tg.UnGetTemp(current_asmdata.CurrAsmList,tempinfo^.location.reference);
  525. excludetempflag(ti_valid);
  526. end;
  527. end;
  528. LOC_CREGISTER,
  529. LOC_REGISTER:
  530. begin
  531. if (not(cs_opt_regvar in current_settings.optimizerswitches) or
  532. (pi_has_label in current_procinfo.flags)) and not(ti_no_final_regsync in tempflags) then
  533. begin
  534. { make sure the register allocator doesn't reuse the }
  535. { register e.g. in the middle of a loop }
  536. {$if defined(cpu32bitalu)}
  537. if tempinfo^.location.size in [OS_64,OS_S64] then
  538. begin
  539. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
  540. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
  541. end
  542. else
  543. {$elseif defined(cpu16bitalu)}
  544. if tempinfo^.location.size in [OS_64,OS_S64] then
  545. begin
  546. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
  547. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register64.reghi));
  548. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
  549. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register64.reglo));
  550. end
  551. else
  552. if tempinfo^.location.size in [OS_32,OS_S32] then
  553. begin
  554. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  555. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register));
  556. end
  557. else
  558. {$elseif defined(cpu8bitalu)}
  559. if tempinfo^.location.size in [OS_64,OS_S64] then
  560. begin
  561. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
  562. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register64.reghi));
  563. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register64.reghi)));
  564. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register64.reghi))));
  565. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
  566. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register64.reglo));
  567. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register64.reglo)));
  568. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register64.reglo))));
  569. end
  570. else
  571. if tempinfo^.location.size in [OS_32,OS_S32] then
  572. begin
  573. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  574. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register));
  575. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register)));
  576. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register))));
  577. end
  578. else
  579. if tempinfo^.location.size in [OS_16,OS_S16] then
  580. begin
  581. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  582. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register));
  583. end
  584. else
  585. {$endif}
  586. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  587. end;
  588. if release_to_normal then
  589. tempinfo^.location.loc := LOC_REGISTER
  590. else
  591. excludetempflag(ti_valid);
  592. end;
  593. LOC_CFPUREGISTER,
  594. LOC_FPUREGISTER:
  595. begin
  596. if (not(cs_opt_regvar in current_settings.optimizerswitches) or
  597. (pi_has_label in current_procinfo.flags)) and not(ti_no_final_regsync in tempflags) then
  598. begin
  599. { make sure the register allocator doesn't reuse the }
  600. { register e.g. in the middle of a loop }
  601. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  602. end;
  603. if release_to_normal then
  604. tempinfo^.location.loc := LOC_FPUREGISTER
  605. else
  606. excludetempflag(ti_valid);
  607. end;
  608. LOC_CMMREGISTER,
  609. LOC_MMREGISTER:
  610. begin
  611. if (not(cs_opt_regvar in current_settings.optimizerswitches) or
  612. (pi_has_label in current_procinfo.flags)) and not(ti_no_final_regsync in tempflags) then
  613. begin
  614. { make sure the register allocator doesn't reuse the }
  615. { register e.g. in the middle of a loop }
  616. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  617. end;
  618. if release_to_normal then
  619. tempinfo^.location.loc := LOC_MMREGISTER
  620. else
  621. excludetempflag(ti_valid);
  622. end;
  623. else
  624. internalerror(200507161);
  625. end;
  626. end;
  627. begin
  628. cnothingnode:=tcgnothingnode;
  629. casmnode:=tcgasmnode;
  630. cstatementnode:=tcgstatementnode;
  631. cblocknode:=tcgblocknode;
  632. ctempcreatenode:=tcgtempcreatenode;
  633. ctemprefnode:=tcgtemprefnode;
  634. ctempdeletenode:=tcgtempdeletenode;
  635. end.