n386ld.pas 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 assembler for load/assignment nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit n386ld;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node,nld;
  23. type
  24. ti386loadnode = class(tloadnode)
  25. procedure pass_2;override;
  26. end;
  27. ti386assignmentnode = class(tassignmentnode)
  28. procedure pass_2;override;
  29. end;
  30. ti386funcretnode = class(tfuncretnode)
  31. procedure pass_2;override;
  32. end;
  33. ti386arrayconstructornode = class(tarrayconstructornode)
  34. procedure pass_2;override;
  35. end;
  36. implementation
  37. uses
  38. globtype,systems,
  39. cobjects,verbose,globals,fmodule,
  40. symconst,symtable,aasm,types,
  41. hcodegen,temp_gen,pass_2,
  42. nmem,ncon,ncnv,
  43. cpubase,cpuasm,
  44. cgai386,tgeni386,n386cnv,n386util,cresstr;
  45. {*****************************************************************************
  46. SecondLoad
  47. *****************************************************************************}
  48. procedure ti386loadnode.pass_2;
  49. var
  50. hregister : tregister;
  51. symtabletype : tsymtabletype;
  52. i : longint;
  53. hp : preference;
  54. s : pasmsymbol;
  55. popeax : boolean;
  56. pushed : tpushed;
  57. hr : treference;
  58. begin
  59. simple_loadn:=true;
  60. reset_reference(location.reference);
  61. case symtableentry^.typ of
  62. { this is only for toasm and toaddr }
  63. absolutesym :
  64. begin
  65. location.reference.symbol:=nil;
  66. if (pabsolutesym(symtableentry)^.abstyp=toaddr) then
  67. begin
  68. if pabsolutesym(symtableentry)^.absseg then
  69. location.reference.segment:=R_FS;
  70. location.reference.offset:=pabsolutesym(symtableentry)^.address;
  71. end
  72. else
  73. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  74. end;
  75. constsym:
  76. begin
  77. if pconstsym(symtableentry)^.consttyp=constresourcestring then
  78. begin
  79. pushusedregisters(pushed,$ff);
  80. emit_const(A_PUSH,S_L,
  81. pconstsym(symtableentry)^.resstrindex);
  82. emit_sym(A_PUSH,S_L,newasmsymbol(pconstsym(symtableentry)^.owner^.name^+'_RESOURCESTRINGLIST'));
  83. emitcall('FPC_GETRESOURCESTRING');
  84. hregister:=getexplicitregister32(R_EAX);
  85. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  86. gettempansistringreference(hr);
  87. decrstringref(resulttype,hr);
  88. emit_reg_ref(A_MOV,S_L,hregister,
  89. newreference(hr));
  90. ungetregister32(hregister);
  91. popusedregisters(pushed);
  92. location.loc:=LOC_MEM;
  93. location.reference:=hr;
  94. end
  95. else
  96. internalerror(22798);
  97. end;
  98. varsym :
  99. begin
  100. hregister:=R_NO;
  101. { C variable }
  102. if (vo_is_C_var in pvarsym(symtableentry)^.varoptions) then
  103. begin
  104. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  105. end
  106. { DLL variable }
  107. else if (vo_is_dll_var in pvarsym(symtableentry)^.varoptions) then
  108. begin
  109. hregister:=getregister32;
  110. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  111. emit_ref_reg(A_MOV,S_L,newreference(location.reference),hregister);
  112. location.reference.symbol:=nil;
  113. location.reference.base:=hregister;
  114. end
  115. { external variable }
  116. else if (vo_is_external in pvarsym(symtableentry)^.varoptions) then
  117. begin
  118. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  119. end
  120. { thread variable }
  121. else if (vo_is_thread_var in pvarsym(symtableentry)^.varoptions) then
  122. begin
  123. popeax:=not(R_EAX in unused);
  124. if popeax then
  125. emit_reg(A_PUSH,S_L,R_EAX);
  126. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  127. emit_ref(A_PUSH,S_L,newreference(location.reference));
  128. { the called procedure isn't allowed to change }
  129. { any register except EAX }
  130. emitcall('FPC_RELOCATE_THREADVAR');
  131. reset_reference(location.reference);
  132. location.reference.base:=getregister32;
  133. emit_reg_reg(A_MOV,S_L,R_EAX,location.reference.base);
  134. if popeax then
  135. emit_reg(A_POP,S_L,R_EAX);
  136. end
  137. { normal variable }
  138. else
  139. begin
  140. symtabletype:=symtable^.symtabletype;
  141. { in case it is a register variable: }
  142. if pvarsym(symtableentry)^.reg<>R_NO then
  143. begin
  144. if pvarsym(symtableentry)^.reg in [R_ST0..R_ST7] then
  145. begin
  146. location.loc:=LOC_CFPUREGISTER;
  147. location.register:=pvarsym(symtableentry)^.reg;
  148. end
  149. else
  150. begin
  151. location.loc:=LOC_CREGISTER;
  152. location.register:=pvarsym(symtableentry)^.reg;
  153. unused:=unused-[pvarsym(symtableentry)^.reg];
  154. end;
  155. end
  156. else
  157. begin
  158. { first handle local and temporary variables }
  159. if (symtabletype in [parasymtable,inlinelocalsymtable,
  160. inlineparasymtable,localsymtable]) then
  161. begin
  162. location.reference.base:=procinfo^.framepointer;
  163. if (symtabletype in [inlinelocalsymtable,
  164. localsymtable]) then
  165. location.reference.offset:=
  166. pvarsym(symtableentry)^.address-symtable^.address_fixup
  167. else
  168. location.reference.offset:=
  169. pvarsym(symtableentry)^.address+symtable^.address_fixup;
  170. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  171. begin
  172. if use_esp_stackframe then
  173. dec(location.reference.offset,
  174. pvarsym(symtableentry)^.getvaluesize)
  175. else
  176. location.reference.offset:=-location.reference.offset;
  177. end;
  178. if (lexlevel>(symtable^.symtablelevel)) then
  179. begin
  180. hregister:=getregister32;
  181. { make a reference }
  182. hp:=new_reference(procinfo^.framepointer,
  183. procinfo^.framepointer_offset);
  184. emit_ref_reg(A_MOV,S_L,hp,hregister);
  185. simple_loadn:=false;
  186. i:=lexlevel-1;
  187. while i>(symtable^.symtablelevel) do
  188. begin
  189. { make a reference }
  190. hp:=new_reference(hregister,8);
  191. emit_ref_reg(A_MOV,S_L,hp,hregister);
  192. dec(i);
  193. end;
  194. location.reference.base:=hregister;
  195. end;
  196. end
  197. else
  198. case symtabletype of
  199. unitsymtable,globalsymtable,
  200. staticsymtable :
  201. begin
  202. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  203. end;
  204. stt_exceptsymtable:
  205. begin
  206. location.reference.base:=procinfo^.framepointer;
  207. location.reference.offset:=pvarsym(symtableentry)^.address;
  208. end;
  209. objectsymtable:
  210. begin
  211. getexplicitregister32(R_ESI);
  212. if (sp_static in pvarsym(symtableentry)^.symoptions) then
  213. begin
  214. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  215. end
  216. else
  217. begin
  218. location.reference.base:=R_ESI;
  219. location.reference.offset:=pvarsym(symtableentry)^.address;
  220. end;
  221. end;
  222. withsymtable:
  223. begin
  224. { make a reference }
  225. { symtable datasize field
  226. contains the offset of the temp
  227. stored }
  228. { hp:=new_reference(procinfo^.framepointer,
  229. symtable^.datasize);
  230. emit_ref_reg(A_MOV,S_L,hp,hregister);}
  231. if nf_islocal in tnode(pwithsymtable(symtable)^.withnode).flags then
  232. begin
  233. location.reference:=twithnode(pwithsymtable(symtable)^.withnode).withreference^;
  234. end
  235. else
  236. begin
  237. hregister:=getregister32;
  238. location.reference.base:=hregister;
  239. emit_ref_reg(A_MOV,S_L,
  240. newreference(twithnode(pwithsymtable(symtable)^.withnode).withreference^),
  241. hregister);
  242. end;
  243. inc(location.reference.offset,pvarsym(symtableentry)^.address);
  244. end;
  245. end;
  246. end;
  247. { in case call by reference, then calculate. Open array
  248. is always an reference! }
  249. if (pvarsym(symtableentry)^.varspez in [vs_var,vs_out]) or
  250. is_open_array(pvarsym(symtableentry)^.vartype.def) or
  251. is_array_of_const(pvarsym(symtableentry)^.vartype.def) or
  252. ((pvarsym(symtableentry)^.varspez=vs_const) and
  253. push_addr_param(pvarsym(symtableentry)^.vartype.def)) then
  254. begin
  255. simple_loadn:=false;
  256. if hregister=R_NO then
  257. hregister:=getregister32;
  258. if location.loc=LOC_CREGISTER then
  259. begin
  260. emit_reg_reg(A_MOV,S_L,
  261. location.register,hregister);
  262. location.loc:=LOC_REFERENCE;
  263. end
  264. else
  265. begin
  266. emit_ref_reg(A_MOV,S_L,
  267. newreference(location.reference),
  268. hregister);
  269. end;
  270. reset_reference(location.reference);
  271. location.reference.base:=hregister;
  272. end;
  273. end;
  274. end;
  275. procsym:
  276. begin
  277. if assigned(left) then
  278. begin
  279. secondpass(left);
  280. location.loc:=LOC_MEM;
  281. gettempofsizereference(8,location.reference);
  282. { load class instance address }
  283. case left.location.loc of
  284. LOC_CREGISTER,
  285. LOC_REGISTER:
  286. begin
  287. hregister:=left.location.register;
  288. ungetregister32(left.location.register);
  289. if (left.resulttype^.deftype<>classrefdef) and
  290. (left.resulttype^.deftype<>objectdef) and
  291. not(pobjectdef(left.resulttype)^.is_class) then
  292. CGMessage(cg_e_illegal_expression);
  293. end;
  294. LOC_MEM,
  295. LOC_REFERENCE:
  296. begin
  297. {$ifndef noAllocEdi}
  298. getexplicitregister32(R_EDI);
  299. {$endif noAllocEdi}
  300. hregister:=R_EDI;
  301. if pobjectdef(left.resulttype)^.is_class then
  302. emit_ref_reg(A_MOV,S_L,
  303. newreference(left.location.reference),R_EDI)
  304. else
  305. emit_ref_reg(A_LEA,S_L,
  306. newreference(left.location.reference),R_EDI);
  307. del_reference(left.location.reference);
  308. ungetiftemp(left.location.reference);
  309. end;
  310. else internalerror(26019);
  311. end;
  312. { store the class instance address }
  313. new(hp);
  314. hp^:=location.reference;
  315. inc(hp^.offset,4);
  316. emit_reg_ref(A_MOV,S_L,
  317. hregister,hp);
  318. { virtual method ? }
  319. if (po_virtualmethod in pprocsym(symtableentry)^.definition^.procoptions) then
  320. begin
  321. new(hp);
  322. reset_reference(hp^);
  323. hp^.base:=hregister;
  324. { load vmt pointer }
  325. emit_ref_reg(A_MOV,S_L,
  326. hp,R_EDI);
  327. {$IfDef regallocfix}
  328. del_reference(hp^);
  329. {$EndIf regallocfix}
  330. { load method address }
  331. new(hp);
  332. reset_reference(hp^);
  333. hp^.base:=R_EDI;
  334. hp^.offset:=pprocsym(symtableentry)^.definition^._class^.vmtmethodoffset(
  335. pprocsym(symtableentry)^.definition^.extnumber);
  336. emit_ref_reg(A_MOV,S_L,
  337. hp,R_EDI);
  338. { ... and store it }
  339. emit_reg_ref(A_MOV,S_L,
  340. R_EDI,newreference(location.reference));
  341. {$ifndef noAllocEdi}
  342. ungetregister32(R_EDI);
  343. {$endif noAllocEdi}
  344. end
  345. else
  346. begin
  347. {$ifndef noAllocEdi}
  348. ungetregister32(R_EDI);
  349. {$endif noAllocEdi}
  350. s:=newasmsymbol(pprocsym(symtableentry)^.definition^.mangledname);
  351. emit_sym_ofs_ref(A_MOV,S_L,s,0,
  352. newreference(location.reference));
  353. end;
  354. end
  355. else
  356. begin
  357. {!!!!! Be aware, work on virtual methods too }
  358. location.reference.symbol:=newasmsymbol(pprocsym(symtableentry)^.definition^.mangledname);
  359. end;
  360. end;
  361. typedconstsym :
  362. begin
  363. location.reference.symbol:=newasmsymbol(symtableentry^.mangledname);
  364. end;
  365. else internalerror(4);
  366. end;
  367. end;
  368. {*****************************************************************************
  369. SecondAssignment
  370. *****************************************************************************}
  371. procedure ti386assignmentnode.pass_2;
  372. var
  373. opsize : topsize;
  374. otlabel,hlabel,oflabel : pasmlabel;
  375. fputyp : tfloattype;
  376. loc : tloc;
  377. r : preference;
  378. ai : paicpu;
  379. op : tasmop;
  380. pushed : boolean;
  381. regspushed : tpushed;
  382. regs_to_push: byte;
  383. ungettemp : boolean;
  384. begin
  385. otlabel:=truelabel;
  386. oflabel:=falselabel;
  387. getlabel(truelabel);
  388. getlabel(falselabel);
  389. { calculate left sides }
  390. if not(nf_concat_string in flags) then
  391. secondpass(left);
  392. if codegenerror then
  393. exit;
  394. if not(left.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
  395. LOC_CREGISTER,LOC_CMMXREGISTER]) then
  396. begin
  397. CGMessage(cg_e_illegal_expression);
  398. exit;
  399. end;
  400. loc:=left.location.loc;
  401. { lets try to optimize this (PM) }
  402. { define a dest_loc that is the location }
  403. { and a ptree to verify that it is the right }
  404. { place to insert it }
  405. {$ifdef test_dest_loc}
  406. if (aktexprlevel<4) then
  407. begin
  408. dest_loc_known:=true;
  409. dest_loc:=left.location;
  410. dest_loc_tree:=right;
  411. end;
  412. {$endif test_dest_loc}
  413. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  414. { can be false }
  415. pushed:=maybe_push(right.registers32,left,false);
  416. secondpass(right);
  417. { restoring here is nonsense for LOC_JMP !! }
  418. { This generated code that was after a jmp and before any
  419. label => unreachable !!
  420. Could this be tested somehow ?? PM }
  421. if pushed and (right.location.loc <>LOC_JUMP) then
  422. restore(left,false);
  423. if codegenerror then
  424. exit;
  425. {$ifdef test_dest_loc}
  426. dest_loc_known:=false;
  427. if in_dest_loc then
  428. begin
  429. truelabel:=otlabel;
  430. falselabel:=oflabel;
  431. in_dest_loc:=false;
  432. exit;
  433. end;
  434. {$endif test_dest_loc}
  435. if left.resulttype^.deftype=stringdef then
  436. begin
  437. if is_ansistring(left.resulttype) then
  438. begin
  439. { before pushing any parameter, we have to save all used }
  440. { registers, but before that we have to release the }
  441. { registers of that node to save uneccessary pushed }
  442. { so be careful, if you think you can optimize that code (FK) }
  443. { nevertheless, this has to be changed, because otherwise the }
  444. { register is released before it's contents are pushed -> }
  445. { problems with the optimizer (JM) }
  446. del_reference(left.location.reference);
  447. ungettemp:=false;
  448. { Find out which registers have to be pushed (JM) }
  449. regs_to_push := $ff;
  450. remove_non_regvars_from_loc(right.location,regs_to_push);
  451. { And push them (JM) }
  452. pushusedregisters(regspushed,regs_to_push);
  453. case right.location.loc of
  454. LOC_REGISTER,LOC_CREGISTER:
  455. begin
  456. exprasmlist^.concat(new(paicpu,op_reg(A_PUSH,S_L,right.location.register)));
  457. ungetregister32(right.location.register);
  458. end;
  459. LOC_REFERENCE,LOC_MEM:
  460. begin
  461. { First release the registers because emit_push_mem may }
  462. { load the reference in edi before pushing and then the }
  463. { dealloc is too late (and optimizations are missed (JM) }
  464. del_reference(right.location.reference);
  465. { This one doesn't need extra registers (JM) }
  466. emit_push_mem(right.location.reference);
  467. ungettemp:=true;
  468. end;
  469. end;
  470. emitpushreferenceaddr(left.location.reference);
  471. del_reference(left.location.reference);
  472. emitcall('FPC_ANSISTR_ASSIGN');
  473. maybe_loadesi;
  474. popusedregisters(regspushed);
  475. if ungettemp then
  476. ungetiftemp(right.location.reference);
  477. end
  478. else
  479. if is_shortstring(left.resulttype) and
  480. not (nf_concat_string in flags) then
  481. begin
  482. if is_ansistring(right.resulttype) then
  483. begin
  484. if (right.nodetype=stringconstn) and
  485. (tstringconstnode(right).len=0) then
  486. begin
  487. emit_const_ref(A_MOV,S_B,
  488. 0,newreference(left.location.reference));
  489. del_reference(left.location.reference);
  490. end
  491. else
  492. loadansi2short(right,left);
  493. end
  494. else
  495. begin
  496. { we do not need destination anymore }
  497. del_reference(left.location.reference);
  498. {del_reference(right.location.reference);
  499. done in loadshortstring }
  500. loadshortstring(right,left);
  501. ungetiftemp(right.location.reference);
  502. end;
  503. end
  504. else if is_longstring(left.resulttype) then
  505. begin
  506. end
  507. else
  508. begin
  509. { its the only thing we have to do }
  510. del_reference(right.location.reference);
  511. end
  512. end
  513. else case right.location.loc of
  514. LOC_REFERENCE,
  515. LOC_MEM : begin
  516. { extra handling for ordinal constants }
  517. if (right.nodetype in [ordconstn,fixconstn]) or
  518. (loc=LOC_CREGISTER) then
  519. begin
  520. case left.resulttype^.size of
  521. 1 : opsize:=S_B;
  522. 2 : opsize:=S_W;
  523. 4 : opsize:=S_L;
  524. { S_L is correct, the copy is done }
  525. { with two moves }
  526. 8 : opsize:=S_L;
  527. end;
  528. if loc=LOC_CREGISTER then
  529. begin
  530. emit_ref_reg(A_MOV,opsize,
  531. newreference(right.location.reference),
  532. left.location.register);
  533. if is_64bitint(right.resulttype) then
  534. begin
  535. r:=newreference(right.location.reference);
  536. inc(r^.offset,4);
  537. emit_ref_reg(A_MOV,opsize,r,
  538. left.location.registerhigh);
  539. end;
  540. {$IfDef regallocfix}
  541. del_reference(right.location.reference);
  542. {$EndIf regallocfix}
  543. end
  544. else
  545. begin
  546. if is_64bitint(right.resulttype) then
  547. begin
  548. emit_const_ref(A_MOV,opsize,
  549. lo(tordconstnode(right).value),
  550. newreference(left.location.reference));
  551. r:=newreference(left.location.reference);
  552. inc(r^.offset,4);
  553. emit_const_ref(A_MOV,opsize,
  554. hi(tordconstnode(right).value),r);
  555. end
  556. else
  557. begin
  558. emit_const_ref(A_MOV,opsize,
  559. right.location.reference.offset,
  560. newreference(left.location.reference));
  561. end;
  562. {$IfDef regallocfix}
  563. del_reference(left.location.reference);
  564. {$EndIf regallocfix}
  565. {emit_const_loc(A_MOV,opsize,
  566. right.location.reference.offset,
  567. left.location);}
  568. end;
  569. end
  570. else if loc=LOC_CFPUREGISTER then
  571. begin
  572. floatloadops(pfloatdef(right.resulttype)^.typ,op,opsize);
  573. emit_ref(op,opsize,
  574. newreference(right.location.reference));
  575. emit_reg(A_FSTP,S_NO,
  576. correct_fpuregister(left.location.register,fpuvaroffset+1));
  577. end
  578. else
  579. begin
  580. if (right.resulttype^.needs_inittable) and
  581. ( (right.resulttype^.deftype<>objectdef) or
  582. not(pobjectdef(right.resulttype)^.is_class)) then
  583. begin
  584. { this would be a problem }
  585. if not(left.resulttype^.needs_inittable) then
  586. internalerror(3457);
  587. { increment source reference counter }
  588. new(r);
  589. reset_reference(r^);
  590. r^.symbol:=right.resulttype^.get_inittable_label;
  591. emitpushreferenceaddr(r^);
  592. emitpushreferenceaddr(right.location.reference);
  593. emitcall('FPC_ADDREF');
  594. { decrement destination reference counter }
  595. new(r);
  596. reset_reference(r^);
  597. r^.symbol:=left.resulttype^.get_inittable_label;
  598. emitpushreferenceaddr(r^);
  599. emitpushreferenceaddr(left.location.reference);
  600. emitcall('FPC_DECREF');
  601. end;
  602. {$ifdef regallocfix}
  603. concatcopy(right.location.reference,
  604. left.location.reference,left.resulttype^.size,true,false);
  605. ungetiftemp(right.location.reference);
  606. {$Else regallocfix}
  607. concatcopy(right.location.reference,
  608. left.location.reference,left.resulttype^.size,false,false);
  609. ungetiftemp(right.location.reference);
  610. {$endif regallocfix}
  611. end;
  612. end;
  613. {$ifdef SUPPORT_MMX}
  614. LOC_CMMXREGISTER,
  615. LOC_MMXREGISTER:
  616. begin
  617. if loc=LOC_CMMXREGISTER then
  618. emit_reg_reg(A_MOVQ,S_NO,
  619. right.location.register,left.location.register)
  620. else
  621. emit_reg_ref(A_MOVQ,S_NO,
  622. right.location.register,newreference(left.location.reference));
  623. end;
  624. {$endif SUPPORT_MMX}
  625. LOC_REGISTER,
  626. LOC_CREGISTER : begin
  627. case right.resulttype^.size of
  628. 1 : opsize:=S_B;
  629. 2 : opsize:=S_W;
  630. 4 : opsize:=S_L;
  631. 8 : opsize:=S_L;
  632. end;
  633. { simplified with op_reg_loc }
  634. if loc=LOC_CREGISTER then
  635. begin
  636. emit_reg_reg(A_MOV,opsize,
  637. right.location.register,
  638. left.location.register);
  639. ungetregister(right.location.register);
  640. end
  641. else
  642. Begin
  643. emit_reg_ref(A_MOV,opsize,
  644. right.location.register,
  645. newreference(left.location.reference));
  646. ungetregister(right.location.register);
  647. {$IfDef regallocfix}
  648. del_reference(left.location.reference);
  649. {$EndIf regallocfix}
  650. end;
  651. if is_64bitint(right.resulttype) then
  652. begin
  653. { simplified with op_reg_loc }
  654. if loc=LOC_CREGISTER then
  655. emit_reg_reg(A_MOV,opsize,
  656. right.location.registerhigh,
  657. left.location.registerhigh)
  658. else
  659. begin
  660. r:=newreference(left.location.reference);
  661. inc(r^.offset,4);
  662. emit_reg_ref(A_MOV,opsize,
  663. right.location.registerhigh,r);
  664. end;
  665. end;
  666. {emit_reg_loc(A_MOV,opsize,
  667. right.location.register,
  668. left.location); }
  669. end;
  670. LOC_FPU : begin
  671. if (left.resulttype^.deftype=floatdef) then
  672. fputyp:=pfloatdef(left.resulttype)^.typ
  673. else
  674. if (right.resulttype^.deftype=floatdef) then
  675. fputyp:=pfloatdef(right.resulttype)^.typ
  676. else
  677. if (right.nodetype=typeconvn) and
  678. (ttypeconvnode(right).left.resulttype^.deftype=floatdef) then
  679. fputyp:=pfloatdef(ttypeconvnode(right).left.resulttype)^.typ
  680. else
  681. fputyp:=s32real;
  682. case loc of
  683. LOC_CFPUREGISTER:
  684. begin
  685. emit_reg(A_FSTP,S_NO,
  686. correct_fpuregister(left.location.register,fpuvaroffset));
  687. dec(fpuvaroffset);
  688. end;
  689. LOC_REFERENCE:
  690. floatstore(fputyp,left.location.reference);
  691. else
  692. internalerror(48991);
  693. end;
  694. end;
  695. LOC_CFPUREGISTER: begin
  696. if (left.resulttype^.deftype=floatdef) then
  697. fputyp:=pfloatdef(left.resulttype)^.typ
  698. else
  699. if (right.resulttype^.deftype=floatdef) then
  700. fputyp:=pfloatdef(right.resulttype)^.typ
  701. else
  702. if (right.nodetype=typeconvn) and
  703. (ttypeconvnode(right).left.resulttype^.deftype=floatdef) then
  704. fputyp:=pfloatdef(ttypeconvnode(right).left.resulttype)^.typ
  705. else
  706. fputyp:=s32real;
  707. emit_reg(A_FLD,S_NO,
  708. correct_fpuregister(right.location.register,fpuvaroffset));
  709. inc(fpuvaroffset);
  710. case loc of
  711. LOC_CFPUREGISTER:
  712. begin
  713. emit_reg(A_FSTP,S_NO,
  714. correct_fpuregister(right.location.register,fpuvaroffset));
  715. dec(fpuvaroffset);
  716. end;
  717. LOC_REFERENCE:
  718. floatstore(fputyp,left.location.reference);
  719. else
  720. internalerror(48992);
  721. end;
  722. end;
  723. LOC_JUMP : begin
  724. getlabel(hlabel);
  725. emitlab(truelabel);
  726. if pushed then
  727. restore(left,false);
  728. if loc=LOC_CREGISTER then
  729. emit_const_reg(A_MOV,S_B,
  730. 1,left.location.register)
  731. else
  732. emit_const_ref(A_MOV,S_B,
  733. 1,newreference(left.location.reference));
  734. {emit_const_loc(A_MOV,S_B,
  735. 1,left.location);}
  736. emitjmp(C_None,hlabel);
  737. emitlab(falselabel);
  738. if pushed then
  739. restore(left,false);
  740. if loc=LOC_CREGISTER then
  741. emit_reg_reg(A_XOR,S_B,
  742. left.location.register,
  743. left.location.register)
  744. else
  745. begin
  746. emit_const_ref(A_MOV,S_B,
  747. 0,newreference(left.location.reference));
  748. {$IfDef regallocfix}
  749. del_reference(left.location.reference);
  750. {$EndIf regallocfix}
  751. end;
  752. emitlab(hlabel);
  753. end;
  754. LOC_FLAGS : begin
  755. if loc=LOC_CREGISTER then
  756. emit_flag2reg(right.location.resflags,left.location.register)
  757. else
  758. begin
  759. ai:=new(paicpu,op_ref(A_Setcc,S_B,newreference(left.location.reference)));
  760. ai^.SetCondition(flag_2_cond[right.location.resflags]);
  761. exprasmlist^.concat(ai);
  762. end;
  763. {$IfDef regallocfix}
  764. del_reference(left.location.reference);
  765. {$EndIf regallocfix}
  766. end;
  767. end;
  768. truelabel:=otlabel;
  769. falselabel:=oflabel;
  770. end;
  771. {*****************************************************************************
  772. SecondFuncRet
  773. *****************************************************************************}
  774. procedure ti386funcretnode.pass_2;
  775. var
  776. hr : tregister;
  777. hp : preference;
  778. pp : pprocinfo;
  779. hr_valid : boolean;
  780. begin
  781. reset_reference(location.reference);
  782. hr_valid:=false;
  783. if (not inlining_procedure) and
  784. (procinfo<>pprocinfo(funcretprocinfo)) then
  785. begin
  786. hr:=getregister32;
  787. hr_valid:=true;
  788. hp:=new_reference(procinfo^.framepointer,
  789. procinfo^.framepointer_offset);
  790. emit_ref_reg(A_MOV,S_L,hp,hr);
  791. pp:=procinfo^.parent;
  792. { walk up the stack frame }
  793. while pp<>pprocinfo(funcretprocinfo) do
  794. begin
  795. hp:=new_reference(hr,
  796. pp^.framepointer_offset);
  797. emit_ref_reg(A_MOV,S_L,hp,hr);
  798. pp:=pp^.parent;
  799. end;
  800. location.reference.base:=hr;
  801. location.reference.offset:=pp^.return_offset;
  802. end
  803. else
  804. begin
  805. location.reference.base:=procinfo^.framepointer;
  806. location.reference.offset:=procinfo^.return_offset;
  807. end;
  808. if ret_in_param(rettype.def) then
  809. begin
  810. if not hr_valid then
  811. hr:=getregister32;
  812. emit_ref_reg(A_MOV,S_L,newreference(location.reference),hr);
  813. location.reference.base:=hr;
  814. location.reference.offset:=0;
  815. end;
  816. end;
  817. {*****************************************************************************
  818. SecondArrayConstruct
  819. *****************************************************************************}
  820. const
  821. vtInteger = 0;
  822. vtBoolean = 1;
  823. vtChar = 2;
  824. vtExtended = 3;
  825. vtString = 4;
  826. vtPointer = 5;
  827. vtPChar = 6;
  828. vtObject = 7;
  829. vtClass = 8;
  830. vtWideChar = 9;
  831. vtPWideChar = 10;
  832. vtAnsiString = 11;
  833. vtCurrency = 12;
  834. vtVariant = 13;
  835. vtInterface = 14;
  836. vtWideString = 15;
  837. vtInt64 = 16;
  838. vtQWord = 17;
  839. procedure ti386arrayconstructornode.pass_2;
  840. var
  841. hp : tarrayconstructornode;
  842. href : treference;
  843. lt : pdef;
  844. vaddr : boolean;
  845. vtype : longint;
  846. freetemp,
  847. dovariant : boolean;
  848. elesize : longint;
  849. begin
  850. dovariant:=(nf_forcevaria in flags) or parraydef(resulttype)^.isvariant;
  851. if dovariant then
  852. elesize:=8
  853. else
  854. begin
  855. elesize:=parraydef(resulttype)^.elesize;
  856. if elesize>4 then
  857. internalerror(8765678);
  858. end;
  859. if not(nf_cargs in flags) then
  860. begin
  861. reset_reference(location.reference);
  862. { Allocate always a temp, also if no elements are required, to
  863. be sure that location is valid (PFV) }
  864. if parraydef(resulttype)^.highrange=-1 then
  865. gettempofsizereference(elesize,location.reference)
  866. else
  867. gettempofsizereference((parraydef(resulttype)^.highrange+1)*elesize,location.reference);
  868. href:=location.reference;
  869. end;
  870. hp:=self;
  871. while assigned(hp) do
  872. begin
  873. if assigned(hp.left) then
  874. begin
  875. freetemp:=true;
  876. secondpass(hp.left);
  877. if codegenerror then
  878. exit;
  879. if dovariant then
  880. begin
  881. { find the correct vtype value }
  882. vtype:=$ff;
  883. vaddr:=false;
  884. lt:=hp.left.resulttype;
  885. case lt^.deftype of
  886. enumdef,
  887. orddef :
  888. begin
  889. if is_64bitint(lt) then
  890. begin
  891. case porddef(lt)^.typ of
  892. s64bit:
  893. vtype:=vtInt64;
  894. u64bit:
  895. vtype:=vtQWord;
  896. end;
  897. freetemp:=false;
  898. vaddr:=true;
  899. end
  900. else if (lt^.deftype=enumdef) or
  901. is_integer(lt) then
  902. vtype:=vtInteger
  903. else
  904. if is_boolean(lt) then
  905. vtype:=vtBoolean
  906. else
  907. if (lt^.deftype=orddef) and (porddef(lt)^.typ=uchar) then
  908. vtype:=vtChar;
  909. end;
  910. floatdef :
  911. begin
  912. vtype:=vtExtended;
  913. vaddr:=true;
  914. freetemp:=false;
  915. end;
  916. procvardef,
  917. pointerdef :
  918. begin
  919. if is_pchar(lt) then
  920. vtype:=vtPChar
  921. else
  922. vtype:=vtPointer;
  923. end;
  924. classrefdef :
  925. vtype:=vtClass;
  926. objectdef :
  927. begin
  928. vtype:=vtObject;
  929. end;
  930. stringdef :
  931. begin
  932. if is_shortstring(lt) then
  933. begin
  934. vtype:=vtString;
  935. vaddr:=true;
  936. freetemp:=false;
  937. end
  938. else
  939. if is_ansistring(lt) then
  940. begin
  941. vtype:=vtAnsiString;
  942. freetemp:=false;
  943. end;
  944. end;
  945. end;
  946. if vtype=$ff then
  947. internalerror(14357);
  948. { write C style pushes or an pascal array }
  949. if nf_cargs in flags then
  950. begin
  951. if vaddr then
  952. begin
  953. emit_to_mem(hp.left.location,hp.left.resulttype);
  954. emit_push_lea_loc(hp.left.location,freetemp);
  955. del_reference(hp.left.location.reference);
  956. end
  957. else
  958. emit_push_loc(hp.left.location);
  959. inc(pushedparasize);
  960. end
  961. else
  962. begin
  963. { write changing field update href to the next element }
  964. inc(href.offset,4);
  965. if vaddr then
  966. begin
  967. emit_to_mem(hp.left.location,hp.left.resulttype);
  968. emit_lea_loc_ref(hp.left.location,href,freetemp);
  969. end
  970. else
  971. begin
  972. emit_mov_loc_ref(hp.left.location,href,S_L,freetemp);
  973. end;
  974. { update href to the vtype field and write it }
  975. dec(href.offset,4);
  976. emit_const_ref(A_MOV,S_L,vtype,newreference(href));
  977. { goto next array element }
  978. inc(href.offset,8);
  979. end;
  980. end
  981. else
  982. { normal array constructor of the same type }
  983. begin
  984. case elesize of
  985. 1 :
  986. emit_mov_loc_ref(hp.left.location,href,S_B,freetemp);
  987. 2 :
  988. emit_mov_loc_ref(hp.left.location,href,S_W,freetemp);
  989. 4 :
  990. emit_mov_loc_ref(hp.left.location,href,S_L,freetemp);
  991. else
  992. internalerror(87656781);
  993. end;
  994. inc(href.offset,elesize);
  995. end;
  996. end;
  997. { load next entry }
  998. hp:=tarrayconstructornode(hp.right);
  999. end;
  1000. end;
  1001. begin
  1002. cloadnode:=ti386loadnode;
  1003. cassignmentnode:=ti386assignmentnode;
  1004. cfuncretnode:=ti386funcretnode;
  1005. carrayconstructornode:=ti386arrayconstructornode;
  1006. end.
  1007. {
  1008. $Log$
  1009. Revision 1.1 2000-10-15 09:33:31 peter
  1010. * moved n386*.pas to i386/ cpu_target dir
  1011. Revision 1.1 2000/10/14 10:14:49 peter
  1012. * moehrendorf oct 2000 rewrite
  1013. }