ncgbas.pas 29 KB

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