cg386ld.pas 45 KB

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