ncgbas.pas 27 KB

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