cg386ld.pas 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 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,
  30. symtable,aasm,types,
  31. hcodegen,temp_gen,pass_2,
  32. {$ifndef OLDASM}
  33. i386base,i386asm,
  34. {$else}
  35. i386,
  36. {$endif}
  37. cgai386,tgeni386,cg386cnv;
  38. {*****************************************************************************
  39. SecondLoad
  40. *****************************************************************************}
  41. procedure secondload(var p : ptree);
  42. var
  43. hregister : tregister;
  44. symtabletype : tsymtabletype;
  45. i : longint;
  46. hp : preference;
  47. s : pasmsymbol;
  48. popeax : boolean;
  49. begin
  50. simple_loadn:=true;
  51. reset_reference(p^.location.reference);
  52. case p^.symtableentry^.typ of
  53. { this is only for toasm and toaddr }
  54. absolutesym :
  55. begin
  56. p^.location.reference.symbol:=nil;
  57. if (pabsolutesym(p^.symtableentry)^.abstyp=toaddr) then
  58. begin
  59. if pabsolutesym(p^.symtableentry)^.absseg then
  60. p^.location.reference.segment:=R_FS;
  61. p^.location.reference.offset:=pabsolutesym(p^.symtableentry)^.address;
  62. end
  63. else
  64. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  65. maybe_concat_external(p^.symtableentry^.owner,p^.symtableentry^.mangledname);
  66. end;
  67. varsym :
  68. begin
  69. hregister:=R_NO;
  70. { C variable }
  71. if (pvarsym(p^.symtableentry)^.var_options and vo_is_C_var)<>0 then
  72. begin
  73. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  74. if (pvarsym(p^.symtableentry)^.var_options and vo_is_external)<>0 then
  75. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  76. end
  77. { DLL variable }
  78. else if (pvarsym(p^.symtableentry)^.var_options and vo_is_dll_var)<>0 then
  79. begin
  80. hregister:=getregister32;
  81. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  82. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.location.reference),hregister)));
  83. p^.location.reference.symbol:=nil;
  84. p^.location.reference.base:=hregister;
  85. end
  86. { external variable }
  87. else if (pvarsym(p^.symtableentry)^.var_options and vo_is_external)<>0 then
  88. begin
  89. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  90. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  91. end
  92. { thread variable }
  93. else if (pvarsym(p^.symtableentry)^.var_options and vo_is_thread_var)<>0 then
  94. begin
  95. popeax:=not(R_EAX in unused);
  96. if popeax then
  97. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EAX)));
  98. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  99. if p^.symtable^.symtabletype=unitsymtable then
  100. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  101. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,newreference(p^.location.reference))));
  102. { the called procedure isn't allowed to change }
  103. { any register except EAX }
  104. emitcall('FPC_RELOCATE_THREADVAR',true);
  105. clear_reference(p^.location.reference);
  106. p^.location.reference.base:=getregister32;
  107. emit_reg_reg(A_MOV,S_L,R_EAX,p^.location.reference.base);
  108. if popeax then
  109. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EAX)));
  110. end
  111. { normal variable }
  112. else
  113. begin
  114. symtabletype:=p^.symtable^.symtabletype;
  115. { in case it is a register variable: }
  116. if pvarsym(p^.symtableentry)^.reg<>R_NO then
  117. begin
  118. p^.location.loc:=LOC_CREGISTER;
  119. p^.location.register:=pvarsym(p^.symtableentry)^.reg;
  120. unused:=unused-[pvarsym(p^.symtableentry)^.reg];
  121. end
  122. else
  123. begin
  124. { first handle local and temporary variables }
  125. if (symtabletype in [parasymtable,inlinelocalsymtable,
  126. inlineparasymtable,localsymtable]) then
  127. begin
  128. p^.location.reference.base:=procinfo.framepointer;
  129. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address+p^.symtable^.address_fixup;
  130. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  131. p^.location.reference.offset:=-p^.location.reference.offset;
  132. if (lexlevel>(p^.symtable^.symtablelevel)) then
  133. begin
  134. hregister:=getregister32;
  135. { make a reference }
  136. hp:=new_reference(procinfo.framepointer,
  137. procinfo.framepointer_offset);
  138. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hregister)));
  139. simple_loadn:=false;
  140. i:=lexlevel-1;
  141. while i>(p^.symtable^.symtablelevel) do
  142. begin
  143. { make a reference }
  144. hp:=new_reference(hregister,8);
  145. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hregister)));
  146. dec(i);
  147. end;
  148. p^.location.reference.base:=hregister;
  149. end;
  150. end
  151. else
  152. case symtabletype of
  153. unitsymtable,globalsymtable,
  154. staticsymtable :
  155. begin
  156. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  157. if symtabletype=unitsymtable then
  158. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  159. end;
  160. stt_exceptsymtable:
  161. begin
  162. p^.location.reference.base:=procinfo.framepointer;
  163. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  164. end;
  165. objectsymtable:
  166. begin
  167. if (pvarsym(p^.symtableentry)^.properties and sp_static)<>0 then
  168. begin
  169. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  170. if p^.symtable^.defowner^.owner^.symtabletype=unitsymtable then
  171. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  172. end
  173. else
  174. begin
  175. p^.location.reference.base:=R_ESI;
  176. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  177. end;
  178. end;
  179. withsymtable:
  180. begin
  181. hregister:=getregister32;
  182. p^.location.reference.base:=hregister;
  183. { make a reference }
  184. { symtable datasize field
  185. contains the offset of the temp
  186. stored }
  187. hp:=new_reference(procinfo.framepointer,
  188. p^.symtable^.datasize);
  189. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hregister)));
  190. p^.location.reference.offset:=
  191. pvarsym(p^.symtableentry)^.address;
  192. end;
  193. end;
  194. end;
  195. { in case call by reference, then calculate. Open array
  196. is always an reference! }
  197. if (pvarsym(p^.symtableentry)^.varspez=vs_var) or
  198. is_open_array(pvarsym(p^.symtableentry)^.definition) or
  199. ((pvarsym(p^.symtableentry)^.varspez=vs_const) and
  200. push_addr_param(pvarsym(p^.symtableentry)^.definition)) then
  201. begin
  202. simple_loadn:=false;
  203. if hregister=R_NO then
  204. hregister:=getregister32;
  205. {$ifdef OLDHIGH}
  206. if is_open_array(pvarsym(p^.symtableentry)^.definition) or
  207. is_open_string(pvarsym(p^.symtableentry)^.definition) then
  208. begin
  209. if (p^.location.reference.base=procinfo.framepointer) then
  210. begin
  211. highframepointer:=p^.location.reference.base;
  212. highoffset:=p^.location.reference.offset;
  213. end
  214. else
  215. begin
  216. highframepointer:=R_EDI;
  217. highoffset:=p^.location.reference.offset;
  218. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,
  219. p^.location.reference.base,R_EDI)));
  220. end;
  221. end;
  222. {$endif}
  223. if p^.location.loc=LOC_CREGISTER then
  224. begin
  225. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,
  226. p^.location.register,hregister)));
  227. p^.location.loc:=LOC_REFERENCE;
  228. end
  229. else
  230. begin
  231. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  232. newreference(p^.location.reference),
  233. hregister)));
  234. end;
  235. clear_reference(p^.location.reference);
  236. p^.location.reference.base:=hregister;
  237. end;
  238. end;
  239. end;
  240. procsym:
  241. begin
  242. if assigned(p^.left) then
  243. begin
  244. secondpass(p^.left);
  245. p^.location.loc:=LOC_MEM;
  246. gettempofsizereference(8,p^.location.reference);
  247. { load class instance address }
  248. case p^.left^.location.loc of
  249. LOC_CREGISTER,
  250. LOC_REGISTER:
  251. begin
  252. hregister:=p^.left^.location.register;
  253. ungetregister32(p^.left^.location.register);
  254. { such code is allowed !
  255. CGMessage(cg_e_illegal_expression); }
  256. end;
  257. LOC_MEM,
  258. LOC_REFERENCE:
  259. begin
  260. hregister:=R_EDI;
  261. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  262. newreference(p^.left^.location.reference),R_EDI)));
  263. del_reference(p^.left^.location.reference);
  264. ungetiftemp(p^.left^.location.reference);
  265. end;
  266. else internalerror(26019);
  267. end;
  268. { store the class instance address }
  269. new(hp);
  270. hp^:=p^.location.reference;
  271. inc(hp^.offset,4);
  272. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  273. R_EDI,hp)));
  274. { virtual method ? }
  275. if (pprocsym(p^.symtableentry)^.definition^.options and povirtualmethod)<>0 then
  276. begin
  277. new(hp);
  278. reset_reference(hp^);
  279. hp^.base:=hregister;
  280. { load vmt pointer }
  281. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  282. hp,R_EDI)));
  283. {$IfDef regallocfix}
  284. del_reference(hp^);
  285. {$EndIf regallocfix}
  286. { load method address }
  287. new(hp);
  288. reset_reference(hp^);
  289. hp^.base:=R_EDI;
  290. hp^.offset:=pprocsym(p^.symtableentry)^.definition^.extnumber*4+12;
  291. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  292. hp,R_EDI)));
  293. { ... and store it }
  294. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  295. R_EDI,newreference(p^.location.reference))));
  296. end
  297. else
  298. begin
  299. s:=newasmsymbol(pprocsym(p^.symtableentry)^.definition^.mangledname);
  300. exprasmlist^.concat(new(pai386,op_sym_ofs_ref(A_MOV,S_L,s,0,
  301. newreference(p^.location.reference))));
  302. maybe_concat_external(p^.symtable,p^.symtableentry^.mangledname);
  303. end;
  304. end
  305. else
  306. begin
  307. {!!!!! Be aware, work on virtual methods too }
  308. p^.location.reference.symbol:=newasmsymbol(pprocsym(p^.symtableentry)^.definition^.mangledname);
  309. maybe_concat_external(p^.symtable,p^.symtableentry^.mangledname);
  310. end;
  311. end;
  312. typedconstsym :
  313. begin
  314. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  315. maybe_concat_external(p^.symtable,p^.symtableentry^.mangledname);
  316. end;
  317. else internalerror(4);
  318. end;
  319. end;
  320. {*****************************************************************************
  321. SecondAssignment
  322. *****************************************************************************}
  323. procedure secondassignment(var p : ptree);
  324. var
  325. opsize : topsize;
  326. otlabel,hlabel,oflabel : plabel;
  327. hregister : tregister;
  328. loc : tloc;
  329. r : preference;
  330. oldrl : plinkedlist;
  331. {$ifndef OLDASM}
  332. ai : pai386;
  333. {$endif}
  334. begin
  335. oldrl:=temptoremove;
  336. temptoremove:=new(plinkedlist,init);
  337. otlabel:=truelabel;
  338. oflabel:=falselabel;
  339. getlabel(truelabel);
  340. getlabel(falselabel);
  341. { calculate left sides }
  342. if not(p^.concat_string) then
  343. secondpass(p^.left);
  344. if codegenerror then
  345. exit;
  346. case p^.left^.location.loc of
  347. LOC_REFERENCE : begin
  348. { in case left operator uses to register }
  349. { but to few are free then LEA }
  350. if (p^.left^.location.reference.base<>R_NO) and
  351. (p^.left^.location.reference.index<>R_NO) and
  352. (usablereg32<p^.right^.registers32) then
  353. begin
  354. del_reference(p^.left^.location.reference);
  355. hregister:=getregister32;
  356. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(
  357. p^.left^.location.reference),
  358. hregister)));
  359. clear_reference(p^.left^.location.reference);
  360. p^.left^.location.reference.base:=hregister;
  361. p^.left^.location.reference.index:=R_NO;
  362. end;
  363. loc:=LOC_REFERENCE;
  364. end;
  365. LOC_CREGISTER:
  366. loc:=LOC_CREGISTER;
  367. LOC_MMXREGISTER:
  368. loc:=LOC_MMXREGISTER;
  369. LOC_CMMXREGISTER:
  370. loc:=LOC_CMMXREGISTER;
  371. else
  372. begin
  373. CGMessage(cg_e_illegal_expression);
  374. exit;
  375. end;
  376. end;
  377. { lets try to optimize this (PM) }
  378. { define a dest_loc that is the location }
  379. { and a ptree to verify that it is the right }
  380. { place to insert it }
  381. {$ifdef test_dest_loc}
  382. if (aktexprlevel<4) then
  383. begin
  384. dest_loc_known:=true;
  385. dest_loc:=p^.left^.location;
  386. dest_loc_tree:=p^.right;
  387. end;
  388. {$endif test_dest_loc}
  389. if (p^.right^.treetype=realconstn) then
  390. begin
  391. if p^.left^.resulttype^.deftype=floatdef then
  392. begin
  393. case pfloatdef(p^.left^.resulttype)^.typ of
  394. s32real : p^.right^.realtyp:=ait_real_32bit;
  395. s64real : p^.right^.realtyp:=ait_real_64bit;
  396. s80real : p^.right^.realtyp:=ait_real_80bit;
  397. end;
  398. end;
  399. end;
  400. secondpass(p^.right);
  401. if codegenerror then
  402. exit;
  403. {$ifdef test_dest_loc}
  404. dest_loc_known:=false;
  405. if in_dest_loc then
  406. begin
  407. truelabel:=otlabel;
  408. falselabel:=oflabel;
  409. in_dest_loc:=false;
  410. exit;
  411. end;
  412. {$endif test_dest_loc}
  413. if p^.left^.resulttype^.deftype=stringdef then
  414. begin
  415. if is_ansistring(p^.left^.resulttype) then
  416. begin
  417. { the source and destinations are released
  418. in loadansistring, because an ansi string can
  419. also be in a register
  420. }
  421. loadansistring(p);
  422. end
  423. else
  424. if is_shortstring(p^.left^.resulttype) and
  425. not (p^.concat_string) then
  426. begin
  427. if is_ansistring(p^.right^.resulttype) then
  428. begin
  429. if (p^.right^.treetype=stringconstn) and
  430. (p^.right^.length=0) then
  431. begin
  432. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,
  433. 0,newreference(p^.left^.location.reference))));
  434. {$IfDef regallocfix}
  435. del_reference(p^.left^.location.reference);
  436. {$EndIf regallocfix}
  437. end
  438. else
  439. loadansi2short(p^.right,p^.left);
  440. end
  441. else
  442. begin
  443. { we do not need destination anymore }
  444. del_reference(p^.left^.location.reference);
  445. del_reference(p^.right^.location.reference);
  446. loadshortstring(p);
  447. ungetiftemp(p^.right^.location.reference);
  448. end;
  449. end
  450. else
  451. begin
  452. { its the only thing we have to do }
  453. del_reference(p^.right^.location.reference);
  454. end
  455. end
  456. else case p^.right^.location.loc of
  457. LOC_REFERENCE,
  458. LOC_MEM : begin
  459. { extra handling for ordinal constants }
  460. if (p^.right^.treetype in [ordconstn,fixconstn]) or
  461. (loc=LOC_CREGISTER) then
  462. begin
  463. case p^.left^.resulttype^.size of
  464. 1 : opsize:=S_B;
  465. 2 : opsize:=S_W;
  466. 4 : opsize:=S_L;
  467. end;
  468. if loc=LOC_CREGISTER then
  469. begin
  470. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  471. newreference(p^.right^.location.reference),
  472. p^.left^.location.register)));
  473. {$IfDef regallocfix}
  474. del_reference(p^.right^.location.reference);
  475. {$EndIf regallocfix}
  476. end
  477. else
  478. begin
  479. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,opsize,
  480. p^.right^.location.reference.offset,
  481. newreference(p^.left^.location.reference))));
  482. {$IfDef regallocfix}
  483. del_reference(p^.left^.location.reference);
  484. {$EndIf regallocfix}
  485. {exprasmlist^.concat(new(pai386,op_const_loc(A_MOV,opsize,
  486. p^.right^.location.reference.offset,
  487. p^.left^.location)));}
  488. end;
  489. end
  490. else
  491. begin
  492. if (p^.right^.resulttype^.needs_inittable) and
  493. ( (p^.right^.resulttype^.deftype<>objectdef) or
  494. not(pobjectdef(p^.right^.resulttype)^.isclass)) then
  495. begin
  496. { this would be a problem }
  497. if not(p^.left^.resulttype^.needs_inittable) then
  498. internalerror(3457);
  499. { increment source reference counter }
  500. new(r);
  501. reset_reference(r^);
  502. r^.symbol:=newasmsymbol(lab2str(p^.right^.resulttype^.get_inittable_label));
  503. emitpushreferenceaddr(exprasmlist,r^);
  504. emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
  505. exprasmlist^.concat(new(pai386,
  506. op_sym(A_CALL,S_NO,newasmsymbol('FPC_ADDREF'))));
  507. if not (cs_compilesystem in aktmoduleswitches) then
  508. concat_external('FPC_ADDREF',EXT_NEAR);
  509. { decrement destination reference counter }
  510. new(r);
  511. reset_reference(r^);
  512. r^.symbol:=newasmsymbol(lab2str(p^.left^.resulttype^.get_inittable_label));
  513. emitpushreferenceaddr(exprasmlist,r^);
  514. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  515. exprasmlist^.concat(new(pai386,
  516. op_sym(A_CALL,S_NO,newasmsymbol('FPC_DECREF'))));
  517. if not(cs_compilesystem in aktmoduleswitches) then
  518. concat_external('FPC_DECREF',EXT_NEAR);
  519. end;
  520. {$ifdef regallocfix}
  521. concatcopy(p^.right^.location.reference,
  522. p^.left^.location.reference,p^.left^.resulttype^.size,true,false);
  523. ungetiftemp(p^.right^.location.reference);
  524. {$Else regallocfix}
  525. concatcopy(p^.right^.location.reference,
  526. p^.left^.location.reference,p^.left^.resulttype^.size,false,false);
  527. ungetiftemp(p^.right^.location.reference);
  528. {$endif regallocfix}
  529. end;
  530. end;
  531. {$ifdef SUPPORT_MMX}
  532. LOC_CMMXREGISTER,
  533. LOC_MMXREGISTER:
  534. begin
  535. if loc=LOC_CMMXREGISTER then
  536. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVQ,S_NO,
  537. p^.right^.location.register,p^.left^.location.register)))
  538. else
  539. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOVQ,S_NO,
  540. p^.right^.location.register,newreference(p^.left^.location.reference))));
  541. end;
  542. {$endif SUPPORT_MMX}
  543. LOC_REGISTER,
  544. LOC_CREGISTER : begin
  545. case p^.right^.resulttype^.size of
  546. 1 : opsize:=S_B;
  547. 2 : opsize:=S_W;
  548. 4 : opsize:=S_L;
  549. 8 : opsize:=S_L;
  550. end;
  551. { simplified with op_reg_loc }
  552. if loc=LOC_CREGISTER then
  553. begin
  554. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,
  555. p^.right^.location.register,
  556. p^.left^.location.register)));
  557. {$IfDef regallocfix}
  558. ungetregister(p^.right^.location.register);
  559. {$EndIf regallocfix}
  560. end
  561. else
  562. Begin
  563. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,
  564. p^.right^.location.register,
  565. newreference(p^.left^.location.reference))));
  566. {$IfDef regallocfix}
  567. ungetregister(p^.right^.location.register);
  568. del_reference(p^.left^.location.reference);
  569. {$EndIf regallocfix}
  570. end;
  571. if is_64bitint(p^.right^.resulttype) then
  572. begin
  573. { simplified with op_reg_loc }
  574. if loc=LOC_CREGISTER then
  575. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,
  576. p^.right^.location.registerhigh,
  577. p^.left^.location.registerhigh)))
  578. else
  579. begin
  580. r:=newreference(p^.left^.location.reference);
  581. inc(r^.offset,4);
  582. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,
  583. p^.right^.location.registerhigh,r)));
  584. end;
  585. end;
  586. {exprasmlist^.concat(new(pai386,op_reg_loc(A_MOV,opsize,
  587. p^.right^.location.register,
  588. p^.left^.location))); }
  589. end;
  590. LOC_FPU : begin
  591. if loc<>LOC_REFERENCE then
  592. internalerror(10010)
  593. else
  594. floatstore(pfloatdef(p^.left^.resulttype)^.typ,
  595. p^.left^.location.reference);
  596. end;
  597. LOC_JUMP : begin
  598. getlabel(hlabel);
  599. emitlab(truelabel);
  600. if loc=LOC_CREGISTER then
  601. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,S_B,
  602. 1,p^.left^.location.register)))
  603. else
  604. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,
  605. 1,newreference(p^.left^.location.reference))));
  606. {exprasmlist^.concat(new(pai386,op_const_loc(A_MOV,S_B,
  607. 1,p^.left^.location)));}
  608. emitjmp(C_None,hlabel);
  609. emitlab(falselabel);
  610. if loc=LOC_CREGISTER then
  611. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,S_B,
  612. p^.left^.location.register,
  613. p^.left^.location.register)))
  614. else
  615. begin
  616. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,
  617. 0,newreference(p^.left^.location.reference))));
  618. {$IfDef regallocfix}
  619. del_reference(p^.left^.location.reference);
  620. {$EndIf regallocfix}
  621. end;
  622. emitlab(hlabel);
  623. end;
  624. LOC_FLAGS : begin
  625. if loc=LOC_CREGISTER then
  626. emit_flag2reg(p^.right^.location.resflags,p^.left^.location.register)
  627. else
  628. {$ifndef OLDASM}
  629. begin
  630. ai:=new(pai386,op_ref(A_Setcc,S_B,newreference(p^.left^.location.reference)));
  631. ai^.SetCondition(flag_2_cond[p^.right^.location.resflags]);
  632. exprasmlist^.concat(ai);
  633. end;
  634. {$else}
  635. exprasmlist^.concat(new(pai386,op_ref(flag_2_set[p^.right^.location.resflags],S_B,
  636. newreference(p^.left^.location.reference))));
  637. {$endif}
  638. {$IfDef regallocfix}
  639. del_reference(p^.left^.location.reference);
  640. {$EndIf regallocfix}
  641. end;
  642. end;
  643. removetemps(exprasmlist,temptoremove);
  644. dispose(temptoremove,done);
  645. temptoremove:=oldrl;
  646. freelabel(truelabel);
  647. freelabel(falselabel);
  648. truelabel:=otlabel;
  649. falselabel:=oflabel;
  650. end;
  651. {*****************************************************************************
  652. SecondFuncRet
  653. *****************************************************************************}
  654. procedure secondfuncret(var p : ptree);
  655. var
  656. hr : tregister;
  657. hp : preference;
  658. pp : pprocinfo;
  659. hr_valid : boolean;
  660. begin
  661. clear_reference(p^.location.reference);
  662. hr_valid:=false;
  663. if @procinfo<>pprocinfo(p^.funcretprocinfo) then
  664. begin
  665. hr:=getregister32;
  666. hr_valid:=true;
  667. hp:=new_reference(procinfo.framepointer,
  668. procinfo.framepointer_offset);
  669. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hr)));
  670. pp:=procinfo.parent;
  671. { walk up the stack frame }
  672. while pp<>pprocinfo(p^.funcretprocinfo) do
  673. begin
  674. hp:=new_reference(hr,
  675. pp^.framepointer_offset);
  676. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hr)));
  677. pp:=pp^.parent;
  678. end;
  679. p^.location.reference.base:=hr;
  680. end
  681. else
  682. p^.location.reference.base:=procinfo.framepointer;
  683. p^.location.reference.offset:=procinfo.retoffset;
  684. if ret_in_param(p^.retdef) then
  685. begin
  686. if not hr_valid then
  687. hr:=getregister32;
  688. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.location.reference),hr)));
  689. p^.location.reference.base:=hr;
  690. p^.location.reference.offset:=0;
  691. end;
  692. end;
  693. {*****************************************************************************
  694. SecondArrayConstruct
  695. *****************************************************************************}
  696. const
  697. vtInteger = 0;
  698. vtBoolean = 1;
  699. vtChar = 2;
  700. vtExtended = 3;
  701. vtString = 4;
  702. vtPointer = 5;
  703. vtPChar = 6;
  704. vtObject = 7;
  705. vtClass = 8;
  706. vtWideChar = 9;
  707. vtPWideChar = 10;
  708. vtAnsiString = 11;
  709. vtCurrency = 12;
  710. vtVariant = 13;
  711. vtInterface = 14;
  712. vtWideString = 15;
  713. vtInt64 = 16;
  714. procedure secondarrayconstruct(var p : ptree);
  715. var
  716. hp : ptree;
  717. href : treference;
  718. lt : pdef;
  719. vaddr : boolean;
  720. vtype : longint;
  721. begin
  722. if not p^.cargs then
  723. begin
  724. clear_reference(p^.location.reference);
  725. gettempofsizereference((parraydef(p^.resulttype)^.highrange+1)*8,p^.location.reference);
  726. href:=p^.location.reference;
  727. end;
  728. hp:=p;
  729. while assigned(hp) do
  730. begin
  731. secondpass(hp^.left);
  732. if codegenerror then
  733. exit;
  734. { find the correct vtype value }
  735. vtype:=$ff;
  736. vaddr:=false;
  737. lt:=hp^.left^.resulttype;
  738. case lt^.deftype of
  739. enumdef,
  740. orddef : begin
  741. if (lt^.deftype=enumdef) or
  742. is_integer(lt) then
  743. vtype:=vtInteger
  744. else
  745. if is_boolean(lt) then
  746. vtype:=vtBoolean
  747. else
  748. if (lt^.deftype=orddef) and (porddef(lt)^.typ=uchar) then
  749. vtype:=vtChar;
  750. end;
  751. floatdef : begin
  752. vtype:=vtExtended;
  753. vaddr:=true;
  754. end;
  755. procvardef,
  756. pointerdef : begin
  757. if is_pchar(lt) then
  758. vtype:=vtPChar
  759. else
  760. vtype:=vtPointer;
  761. end;
  762. classrefdef : vtype:=vtClass;
  763. objectdef : begin
  764. vtype:=vtObject;
  765. end;
  766. stringdef : begin
  767. if is_shortstring(lt) then
  768. begin
  769. vtype:=vtString;
  770. vaddr:=true;
  771. end
  772. else
  773. if is_ansistring(lt) then
  774. vtype:=vtAnsiString;
  775. end;
  776. end;
  777. if vtype=$ff then
  778. internalerror(14357);
  779. { write C style pushes or an pascal array }
  780. if p^.cargs then
  781. begin
  782. if vaddr then
  783. begin
  784. emit_to_reference(hp^.left);
  785. emit_push_lea_loc(hp^.left^.location);
  786. end
  787. else
  788. emit_push_loc(hp^.left^.location);
  789. end
  790. else
  791. begin
  792. { update href to the vtype field and write it }
  793. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,
  794. vtype,newreference(href))));
  795. inc(href.offset,4);
  796. { write changing field update href to the next element }
  797. if vaddr then
  798. begin
  799. emit_to_reference(hp^.left);
  800. emit_lea_loc_ref(hp^.left^.location,href);
  801. end
  802. else
  803. emit_mov_loc_ref(hp^.left^.location,href);
  804. inc(href.offset,4);
  805. end;
  806. { load next entry }
  807. hp:=hp^.right;
  808. end;
  809. end;
  810. end.
  811. {
  812. $Log$
  813. Revision 1.53 1999-05-06 09:05:16 peter
  814. * generic write_float and str_float
  815. * fixed constant float conversions
  816. Revision 1.52 1999/05/01 13:24:10 peter
  817. * merged nasm compiler
  818. * old asm moved to oldasm/
  819. Revision 1.51 1999/04/28 06:01:55 florian
  820. * changes of Bruessel:
  821. + message handler can now take an explicit self
  822. * typinfo fixed: sometimes the type names weren't written
  823. * the type checking for pointer comparisations and subtraction
  824. and are now more strict (was also buggy)
  825. * small bug fix to link.pas to support compiling on another
  826. drive
  827. * probable bug in popt386 fixed: call/jmp => push/jmp
  828. transformation didn't count correctly the jmp references
  829. + threadvar support
  830. * warning if ln/sqrt gets an invalid constant argument
  831. Revision 1.50 1999/04/16 13:42:26 jonas
  832. * more regalloc fixes (still not complete)
  833. Revision 1.49 1999/04/13 18:57:48 florian
  834. * classes which contain ansistring get unnecessary calls
  835. to addref/decref when they are assigned, fixed
  836. Revision 1.48 1999/04/09 15:48:47 jonas
  837. * added fix for missing register deallocation (-dregallocfix)
  838. Revision 1.47 1999/03/31 13:55:07 peter
  839. * assembler inlining working for ag386bin
  840. Revision 1.46 1999/03/24 23:16:52 peter
  841. * fixed bugs 212,222,225,227,229,231,233
  842. Revision 1.45 1999/02/25 21:02:28 peter
  843. * ag386bin updates
  844. + coff writer
  845. Revision 1.44 1999/02/22 02:15:12 peter
  846. * updates for ag386bin
  847. Revision 1.43 1999/01/27 00:13:54 florian
  848. * "procedure of object"-stuff fixed
  849. Revision 1.42 1999/01/21 22:10:40 peter
  850. * fixed array of const
  851. * generic platform independent high() support
  852. Revision 1.41 1999/01/20 10:20:18 peter
  853. * don't make localvar copies for assembler procedures
  854. Revision 1.40 1998/12/30 13:41:07 peter
  855. * released valuepara
  856. Revision 1.39 1998/12/19 00:23:45 florian
  857. * ansistring memory leaks fixed
  858. Revision 1.38 1998/12/11 00:02:51 peter
  859. + globtype,tokens,version unit splitted from globals
  860. Revision 1.37 1998/12/10 09:47:17 florian
  861. + basic operations with int64/qord (compiler with -dint64)
  862. + rtti of enumerations extended: names are now written
  863. Revision 1.36 1998/12/04 10:18:06 florian
  864. * some stuff for procedures of object added
  865. * bug with overridden virtual constructors fixed (reported by Italo Gomes)
  866. Revision 1.35 1998/11/30 09:43:04 pierre
  867. * some range check bugs fixed (still not working !)
  868. + added DLL writing support for win32 (also accepts variables)
  869. + TempAnsi for code that could be used for Temporary ansi strings
  870. handling
  871. Revision 1.34 1998/11/28 16:20:48 peter
  872. + support for dll variables
  873. Revision 1.33 1998/11/27 14:50:33 peter
  874. + open strings, $P switch support
  875. Revision 1.32 1998/11/26 09:53:36 florian
  876. * for classes no init/final. code is necessary, fixed
  877. Revision 1.31 1998/11/20 15:35:54 florian
  878. * problems with rtti fixed, hope it works
  879. Revision 1.30 1998/11/18 17:45:24 peter
  880. * fixes for VALUEPARA
  881. Revision 1.29 1998/11/18 15:44:11 peter
  882. * VALUEPARA for tp7 compatible value parameters
  883. Revision 1.28 1998/11/17 11:32:44 peter
  884. * optimize str:='' in H+ mode
  885. + -! to test ansistrings
  886. Revision 1.27 1998/11/16 15:35:39 peter
  887. * rename laod/copystring -> load/copyshortstring
  888. * fixed int-bool cnv bug
  889. + char-ansistring conversion
  890. Revision 1.26 1998/11/10 10:09:10 peter
  891. * va_list -> array of const
  892. Revision 1.25 1998/11/05 12:02:35 peter
  893. * released useansistring
  894. * removed -Sv, its now available in fpc modes
  895. Revision 1.24 1998/10/14 08:47:14 pierre
  896. * bugs in secondfuncret for result in subprocedures removed
  897. Revision 1.23 1998/10/06 17:16:44 pierre
  898. * some memory leaks fixed (thanks to Peter for heaptrc !)
  899. Revision 1.22 1998/10/01 09:22:53 peter
  900. * fixed value openarray
  901. * ungettemp of arrayconstruct
  902. Revision 1.21 1998/09/28 11:07:39 peter
  903. + floatdef support for array of const
  904. Revision 1.20 1998/09/24 14:26:03 peter
  905. * updated for new tvarrec
  906. Revision 1.19 1998/09/23 17:49:59 peter
  907. * high(arrayconstructor) is now correct
  908. * procvardef support for variant record
  909. Revision 1.18 1998/09/23 09:58:48 peter
  910. * first working array of const things
  911. Revision 1.17 1998/09/20 18:00:19 florian
  912. * small compiling problems fixed
  913. Revision 1.16 1998/09/20 17:46:48 florian
  914. * some things regarding ansistrings fixed
  915. Revision 1.15 1998/09/17 09:42:16 peter
  916. + pass_2 for cg386
  917. * Message() -> CGMessage() for pass_1/pass_2
  918. Revision 1.14 1998/09/14 10:43:50 peter
  919. * all internal RTL functions start with FPC_
  920. Revision 1.13 1998/09/04 12:24:24 florian
  921. * bug0159 fixed
  922. Revision 1.12 1998/09/04 11:55:17 florian
  923. * problem with -Or fixed
  924. Revision 1.11 1998/09/03 16:03:14 florian
  925. + rtti generation
  926. * init table generation changed
  927. Revision 1.10 1998/08/21 14:08:40 pierre
  928. + TEST_FUNCRET now default (old code removed)
  929. works also for m68k (at least compiles)
  930. Revision 1.9 1998/08/20 09:26:37 pierre
  931. + funcret setting in underproc testing
  932. compile with _dTEST_FUNCRET
  933. Revision 1.8 1998/08/10 14:49:48 peter
  934. + localswitches, moduleswitches, globalswitches splitting
  935. Revision 1.7 1998/07/30 13:30:33 florian
  936. * final implemenation of exception support, maybe it needs
  937. some fixes :)
  938. Revision 1.6 1998/07/26 21:58:57 florian
  939. + better support for switch $H
  940. + index access to ansi strings added
  941. + assigment of data (records/arrays) containing ansi strings
  942. Revision 1.5 1998/07/24 22:16:54 florian
  943. * internal error 10 together with array access fixed. I hope
  944. that's the final fix.
  945. Revision 1.4 1998/06/11 13:58:45 peter
  946. * fixed too long line
  947. Revision 1.3 1998/06/09 16:01:35 pierre
  948. + added procedure directive parsing for procvars
  949. (accepted are popstack cdecl and pascal)
  950. + added C vars with the following syntax
  951. var C calias 'true_c_name';(can be followed by external)
  952. reason is that you must add the Cprefix
  953. which is target dependent
  954. Revision 1.2 1998/06/08 13:13:34 pierre
  955. + temporary variables now in temp_gen.pas unit
  956. because it is processor independent
  957. * mppc68k.bat modified to undefine i386 and support_mmx
  958. (which are defaults for i386)
  959. Revision 1.1 1998/06/05 17:44:12 peter
  960. * splitted cgi386
  961. }