cg386ld.pas 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  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_extended;
  397. { what about f32bit and s64bit }
  398. end;
  399. end;
  400. end;
  401. secondpass(p^.right);
  402. if codegenerror then
  403. exit;
  404. {$ifdef test_dest_loc}
  405. dest_loc_known:=false;
  406. if in_dest_loc then
  407. begin
  408. truelabel:=otlabel;
  409. falselabel:=oflabel;
  410. in_dest_loc:=false;
  411. exit;
  412. end;
  413. {$endif test_dest_loc}
  414. if p^.left^.resulttype^.deftype=stringdef then
  415. begin
  416. if is_ansistring(p^.left^.resulttype) then
  417. begin
  418. { the source and destinations are released
  419. in loadansistring, because an ansi string can
  420. also be in a register
  421. }
  422. loadansistring(p);
  423. end
  424. else
  425. if is_shortstring(p^.left^.resulttype) and
  426. not (p^.concat_string) then
  427. begin
  428. if is_ansistring(p^.right^.resulttype) then
  429. begin
  430. if (p^.right^.treetype=stringconstn) and
  431. (p^.right^.length=0) then
  432. begin
  433. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,
  434. 0,newreference(p^.left^.location.reference))));
  435. {$IfDef regallocfix}
  436. del_reference(p^.left^.location.reference);
  437. {$EndIf regallocfix}
  438. end
  439. else
  440. loadansi2short(p^.right,p^.left);
  441. end
  442. else
  443. begin
  444. { we do not need destination anymore }
  445. del_reference(p^.left^.location.reference);
  446. del_reference(p^.right^.location.reference);
  447. loadshortstring(p);
  448. ungetiftemp(p^.right^.location.reference);
  449. end;
  450. end
  451. else
  452. begin
  453. { its the only thing we have to do }
  454. del_reference(p^.right^.location.reference);
  455. end
  456. end
  457. else case p^.right^.location.loc of
  458. LOC_REFERENCE,
  459. LOC_MEM : begin
  460. { extra handling for ordinal constants }
  461. if (p^.right^.treetype in [ordconstn,fixconstn]) or
  462. (loc=LOC_CREGISTER) then
  463. begin
  464. case p^.left^.resulttype^.size of
  465. 1 : opsize:=S_B;
  466. 2 : opsize:=S_W;
  467. 4 : opsize:=S_L;
  468. end;
  469. if loc=LOC_CREGISTER then
  470. begin
  471. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  472. newreference(p^.right^.location.reference),
  473. p^.left^.location.register)));
  474. {$IfDef regallocfix}
  475. del_reference(p^.right^.location.reference);
  476. {$EndIf regallocfix}
  477. end
  478. else
  479. begin
  480. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,opsize,
  481. p^.right^.location.reference.offset,
  482. newreference(p^.left^.location.reference))));
  483. {$IfDef regallocfix}
  484. del_reference(p^.left^.location.reference);
  485. {$EndIf regallocfix}
  486. {exprasmlist^.concat(new(pai386,op_const_loc(A_MOV,opsize,
  487. p^.right^.location.reference.offset,
  488. p^.left^.location)));}
  489. end;
  490. end
  491. else
  492. begin
  493. if (p^.right^.resulttype^.needs_inittable) and
  494. ( (p^.right^.resulttype^.deftype<>objectdef) or
  495. not(pobjectdef(p^.right^.resulttype)^.isclass)) then
  496. begin
  497. { this would be a problem }
  498. if not(p^.left^.resulttype^.needs_inittable) then
  499. internalerror(3457);
  500. { increment source reference counter }
  501. new(r);
  502. reset_reference(r^);
  503. r^.symbol:=newasmsymbol(lab2str(p^.right^.resulttype^.get_inittable_label));
  504. emitpushreferenceaddr(exprasmlist,r^);
  505. emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
  506. exprasmlist^.concat(new(pai386,
  507. op_sym(A_CALL,S_NO,newasmsymbol('FPC_ADDREF'))));
  508. if not (cs_compilesystem in aktmoduleswitches) then
  509. concat_external('FPC_ADDREF',EXT_NEAR);
  510. { decrement destination reference counter }
  511. new(r);
  512. reset_reference(r^);
  513. r^.symbol:=newasmsymbol(lab2str(p^.left^.resulttype^.get_inittable_label));
  514. emitpushreferenceaddr(exprasmlist,r^);
  515. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  516. exprasmlist^.concat(new(pai386,
  517. op_sym(A_CALL,S_NO,newasmsymbol('FPC_DECREF'))));
  518. if not(cs_compilesystem in aktmoduleswitches) then
  519. concat_external('FPC_DECREF',EXT_NEAR);
  520. end;
  521. {$ifdef regallocfix}
  522. concatcopy(p^.right^.location.reference,
  523. p^.left^.location.reference,p^.left^.resulttype^.size,true,false);
  524. ungetiftemp(p^.right^.location.reference);
  525. {$Else regallocfix}
  526. concatcopy(p^.right^.location.reference,
  527. p^.left^.location.reference,p^.left^.resulttype^.size,false,false);
  528. ungetiftemp(p^.right^.location.reference);
  529. {$endif regallocfix}
  530. end;
  531. end;
  532. {$ifdef SUPPORT_MMX}
  533. LOC_CMMXREGISTER,
  534. LOC_MMXREGISTER:
  535. begin
  536. if loc=LOC_CMMXREGISTER then
  537. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVQ,S_NO,
  538. p^.right^.location.register,p^.left^.location.register)))
  539. else
  540. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOVQ,S_NO,
  541. p^.right^.location.register,newreference(p^.left^.location.reference))));
  542. end;
  543. {$endif SUPPORT_MMX}
  544. LOC_REGISTER,
  545. LOC_CREGISTER : begin
  546. case p^.right^.resulttype^.size of
  547. 1 : opsize:=S_B;
  548. 2 : opsize:=S_W;
  549. 4 : opsize:=S_L;
  550. 8 : opsize:=S_L;
  551. end;
  552. { simplified with op_reg_loc }
  553. if loc=LOC_CREGISTER then
  554. begin
  555. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,
  556. p^.right^.location.register,
  557. p^.left^.location.register)));
  558. {$IfDef regallocfix}
  559. ungetregister(p^.right^.location.register);
  560. {$EndIf regallocfix}
  561. end
  562. else
  563. Begin
  564. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,
  565. p^.right^.location.register,
  566. newreference(p^.left^.location.reference))));
  567. {$IfDef regallocfix}
  568. ungetregister(p^.right^.location.register);
  569. del_reference(p^.left^.location.reference);
  570. {$EndIf regallocfix}
  571. end;
  572. if is_64bitint(p^.right^.resulttype) then
  573. begin
  574. { simplified with op_reg_loc }
  575. if loc=LOC_CREGISTER then
  576. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,
  577. p^.right^.location.registerhigh,
  578. p^.left^.location.registerhigh)))
  579. else
  580. begin
  581. r:=newreference(p^.left^.location.reference);
  582. inc(r^.offset,4);
  583. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,
  584. p^.right^.location.registerhigh,r)));
  585. end;
  586. end;
  587. {exprasmlist^.concat(new(pai386,op_reg_loc(A_MOV,opsize,
  588. p^.right^.location.register,
  589. p^.left^.location))); }
  590. end;
  591. LOC_FPU : begin
  592. if loc<>LOC_REFERENCE then
  593. internalerror(10010)
  594. else
  595. floatstore(pfloatdef(p^.left^.resulttype)^.typ,
  596. p^.left^.location.reference);
  597. end;
  598. LOC_JUMP : begin
  599. getlabel(hlabel);
  600. emitlab(truelabel);
  601. if loc=LOC_CREGISTER then
  602. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,S_B,
  603. 1,p^.left^.location.register)))
  604. else
  605. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,
  606. 1,newreference(p^.left^.location.reference))));
  607. {exprasmlist^.concat(new(pai386,op_const_loc(A_MOV,S_B,
  608. 1,p^.left^.location)));}
  609. emitjmp(C_None,hlabel);
  610. emitlab(falselabel);
  611. if loc=LOC_CREGISTER then
  612. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,S_B,
  613. p^.left^.location.register,
  614. p^.left^.location.register)))
  615. else
  616. begin
  617. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,
  618. 0,newreference(p^.left^.location.reference))));
  619. {$IfDef regallocfix}
  620. del_reference(p^.left^.location.reference);
  621. {$EndIf regallocfix}
  622. end;
  623. emitlab(hlabel);
  624. end;
  625. LOC_FLAGS : begin
  626. if loc=LOC_CREGISTER then
  627. emit_flag2reg(p^.right^.location.resflags,p^.left^.location.register)
  628. else
  629. {$ifndef OLDASM}
  630. begin
  631. ai:=new(pai386,op_ref(A_Setcc,S_B,newreference(p^.left^.location.reference)));
  632. ai^.SetCondition(flag_2_cond[p^.right^.location.resflags]);
  633. exprasmlist^.concat(ai);
  634. end;
  635. {$else}
  636. exprasmlist^.concat(new(pai386,op_ref(flag_2_set[p^.right^.location.resflags],S_B,
  637. newreference(p^.left^.location.reference))));
  638. {$endif}
  639. {$IfDef regallocfix}
  640. del_reference(p^.left^.location.reference);
  641. {$EndIf regallocfix}
  642. end;
  643. end;
  644. removetemps(exprasmlist,temptoremove);
  645. dispose(temptoremove,done);
  646. temptoremove:=oldrl;
  647. freelabel(truelabel);
  648. freelabel(falselabel);
  649. truelabel:=otlabel;
  650. falselabel:=oflabel;
  651. end;
  652. {*****************************************************************************
  653. SecondFuncRet
  654. *****************************************************************************}
  655. procedure secondfuncret(var p : ptree);
  656. var
  657. hr : tregister;
  658. hp : preference;
  659. pp : pprocinfo;
  660. hr_valid : boolean;
  661. begin
  662. clear_reference(p^.location.reference);
  663. hr_valid:=false;
  664. if @procinfo<>pprocinfo(p^.funcretprocinfo) then
  665. begin
  666. hr:=getregister32;
  667. hr_valid:=true;
  668. hp:=new_reference(procinfo.framepointer,
  669. procinfo.framepointer_offset);
  670. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hr)));
  671. pp:=procinfo.parent;
  672. { walk up the stack frame }
  673. while pp<>pprocinfo(p^.funcretprocinfo) do
  674. begin
  675. hp:=new_reference(hr,
  676. pp^.framepointer_offset);
  677. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hr)));
  678. pp:=pp^.parent;
  679. end;
  680. p^.location.reference.base:=hr;
  681. end
  682. else
  683. p^.location.reference.base:=procinfo.framepointer;
  684. p^.location.reference.offset:=procinfo.retoffset;
  685. if ret_in_param(p^.retdef) then
  686. begin
  687. if not hr_valid then
  688. hr:=getregister32;
  689. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.location.reference),hr)));
  690. p^.location.reference.base:=hr;
  691. p^.location.reference.offset:=0;
  692. end;
  693. end;
  694. {*****************************************************************************
  695. SecondArrayConstruct
  696. *****************************************************************************}
  697. const
  698. vtInteger = 0;
  699. vtBoolean = 1;
  700. vtChar = 2;
  701. vtExtended = 3;
  702. vtString = 4;
  703. vtPointer = 5;
  704. vtPChar = 6;
  705. vtObject = 7;
  706. vtClass = 8;
  707. vtWideChar = 9;
  708. vtPWideChar = 10;
  709. vtAnsiString = 11;
  710. vtCurrency = 12;
  711. vtVariant = 13;
  712. vtInterface = 14;
  713. vtWideString = 15;
  714. vtInt64 = 16;
  715. procedure secondarrayconstruct(var p : ptree);
  716. var
  717. hp : ptree;
  718. href : treference;
  719. lt : pdef;
  720. vaddr : boolean;
  721. vtype : longint;
  722. begin
  723. if not p^.cargs then
  724. begin
  725. clear_reference(p^.location.reference);
  726. gettempofsizereference((parraydef(p^.resulttype)^.highrange+1)*8,p^.location.reference);
  727. href:=p^.location.reference;
  728. end;
  729. hp:=p;
  730. while assigned(hp) do
  731. begin
  732. secondpass(hp^.left);
  733. if codegenerror then
  734. exit;
  735. { find the correct vtype value }
  736. vtype:=$ff;
  737. vaddr:=false;
  738. lt:=hp^.left^.resulttype;
  739. case lt^.deftype of
  740. enumdef,
  741. orddef : begin
  742. if (lt^.deftype=enumdef) or
  743. is_integer(lt) then
  744. vtype:=vtInteger
  745. else
  746. if is_boolean(lt) then
  747. vtype:=vtBoolean
  748. else
  749. if (lt^.deftype=orddef) and (porddef(lt)^.typ=uchar) then
  750. vtype:=vtChar;
  751. end;
  752. floatdef : begin
  753. vtype:=vtExtended;
  754. vaddr:=true;
  755. end;
  756. procvardef,
  757. pointerdef : begin
  758. if is_pchar(lt) then
  759. vtype:=vtPChar
  760. else
  761. vtype:=vtPointer;
  762. end;
  763. classrefdef : vtype:=vtClass;
  764. objectdef : begin
  765. vtype:=vtObject;
  766. end;
  767. stringdef : begin
  768. if is_shortstring(lt) then
  769. begin
  770. vtype:=vtString;
  771. vaddr:=true;
  772. end
  773. else
  774. if is_ansistring(lt) then
  775. vtype:=vtAnsiString;
  776. end;
  777. end;
  778. if vtype=$ff then
  779. internalerror(14357);
  780. { write C style pushes or an pascal array }
  781. if p^.cargs then
  782. begin
  783. if vaddr then
  784. begin
  785. emit_to_reference(hp^.left);
  786. emit_push_lea_loc(hp^.left^.location);
  787. end
  788. else
  789. emit_push_loc(hp^.left^.location);
  790. end
  791. else
  792. begin
  793. { update href to the vtype field and write it }
  794. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,
  795. vtype,newreference(href))));
  796. inc(href.offset,4);
  797. { write changing field update href to the next element }
  798. if vaddr then
  799. begin
  800. emit_to_reference(hp^.left);
  801. emit_lea_loc_ref(hp^.left^.location,href);
  802. end
  803. else
  804. emit_mov_loc_ref(hp^.left^.location,href);
  805. inc(href.offset,4);
  806. end;
  807. { load next entry }
  808. hp:=hp^.right;
  809. end;
  810. end;
  811. end.
  812. {
  813. $Log$
  814. Revision 1.52 1999-05-01 13:24:10 peter
  815. * merged nasm compiler
  816. * old asm moved to oldasm/
  817. Revision 1.51 1999/04/28 06:01:55 florian
  818. * changes of Bruessel:
  819. + message handler can now take an explicit self
  820. * typinfo fixed: sometimes the type names weren't written
  821. * the type checking for pointer comparisations and subtraction
  822. and are now more strict (was also buggy)
  823. * small bug fix to link.pas to support compiling on another
  824. drive
  825. * probable bug in popt386 fixed: call/jmp => push/jmp
  826. transformation didn't count correctly the jmp references
  827. + threadvar support
  828. * warning if ln/sqrt gets an invalid constant argument
  829. Revision 1.50 1999/04/16 13:42:26 jonas
  830. * more regalloc fixes (still not complete)
  831. Revision 1.49 1999/04/13 18:57:48 florian
  832. * classes which contain ansistring get unnecessary calls
  833. to addref/decref when they are assigned, fixed
  834. Revision 1.48 1999/04/09 15:48:47 jonas
  835. * added fix for missing register deallocation (-dregallocfix)
  836. Revision 1.47 1999/03/31 13:55:07 peter
  837. * assembler inlining working for ag386bin
  838. Revision 1.46 1999/03/24 23:16:52 peter
  839. * fixed bugs 212,222,225,227,229,231,233
  840. Revision 1.45 1999/02/25 21:02:28 peter
  841. * ag386bin updates
  842. + coff writer
  843. Revision 1.44 1999/02/22 02:15:12 peter
  844. * updates for ag386bin
  845. Revision 1.43 1999/01/27 00:13:54 florian
  846. * "procedure of object"-stuff fixed
  847. Revision 1.42 1999/01/21 22:10:40 peter
  848. * fixed array of const
  849. * generic platform independent high() support
  850. Revision 1.41 1999/01/20 10:20:18 peter
  851. * don't make localvar copies for assembler procedures
  852. Revision 1.40 1998/12/30 13:41:07 peter
  853. * released valuepara
  854. Revision 1.39 1998/12/19 00:23:45 florian
  855. * ansistring memory leaks fixed
  856. Revision 1.38 1998/12/11 00:02:51 peter
  857. + globtype,tokens,version unit splitted from globals
  858. Revision 1.37 1998/12/10 09:47:17 florian
  859. + basic operations with int64/qord (compiler with -dint64)
  860. + rtti of enumerations extended: names are now written
  861. Revision 1.36 1998/12/04 10:18:06 florian
  862. * some stuff for procedures of object added
  863. * bug with overridden virtual constructors fixed (reported by Italo Gomes)
  864. Revision 1.35 1998/11/30 09:43:04 pierre
  865. * some range check bugs fixed (still not working !)
  866. + added DLL writing support for win32 (also accepts variables)
  867. + TempAnsi for code that could be used for Temporary ansi strings
  868. handling
  869. Revision 1.34 1998/11/28 16:20:48 peter
  870. + support for dll variables
  871. Revision 1.33 1998/11/27 14:50:33 peter
  872. + open strings, $P switch support
  873. Revision 1.32 1998/11/26 09:53:36 florian
  874. * for classes no init/final. code is necessary, fixed
  875. Revision 1.31 1998/11/20 15:35:54 florian
  876. * problems with rtti fixed, hope it works
  877. Revision 1.30 1998/11/18 17:45:24 peter
  878. * fixes for VALUEPARA
  879. Revision 1.29 1998/11/18 15:44:11 peter
  880. * VALUEPARA for tp7 compatible value parameters
  881. Revision 1.28 1998/11/17 11:32:44 peter
  882. * optimize str:='' in H+ mode
  883. + -! to test ansistrings
  884. Revision 1.27 1998/11/16 15:35:39 peter
  885. * rename laod/copystring -> load/copyshortstring
  886. * fixed int-bool cnv bug
  887. + char-ansistring conversion
  888. Revision 1.26 1998/11/10 10:09:10 peter
  889. * va_list -> array of const
  890. Revision 1.25 1998/11/05 12:02:35 peter
  891. * released useansistring
  892. * removed -Sv, its now available in fpc modes
  893. Revision 1.24 1998/10/14 08:47:14 pierre
  894. * bugs in secondfuncret for result in subprocedures removed
  895. Revision 1.23 1998/10/06 17:16:44 pierre
  896. * some memory leaks fixed (thanks to Peter for heaptrc !)
  897. Revision 1.22 1998/10/01 09:22:53 peter
  898. * fixed value openarray
  899. * ungettemp of arrayconstruct
  900. Revision 1.21 1998/09/28 11:07:39 peter
  901. + floatdef support for array of const
  902. Revision 1.20 1998/09/24 14:26:03 peter
  903. * updated for new tvarrec
  904. Revision 1.19 1998/09/23 17:49:59 peter
  905. * high(arrayconstructor) is now correct
  906. * procvardef support for variant record
  907. Revision 1.18 1998/09/23 09:58:48 peter
  908. * first working array of const things
  909. Revision 1.17 1998/09/20 18:00:19 florian
  910. * small compiling problems fixed
  911. Revision 1.16 1998/09/20 17:46:48 florian
  912. * some things regarding ansistrings fixed
  913. Revision 1.15 1998/09/17 09:42:16 peter
  914. + pass_2 for cg386
  915. * Message() -> CGMessage() for pass_1/pass_2
  916. Revision 1.14 1998/09/14 10:43:50 peter
  917. * all internal RTL functions start with FPC_
  918. Revision 1.13 1998/09/04 12:24:24 florian
  919. * bug0159 fixed
  920. Revision 1.12 1998/09/04 11:55:17 florian
  921. * problem with -Or fixed
  922. Revision 1.11 1998/09/03 16:03:14 florian
  923. + rtti generation
  924. * init table generation changed
  925. Revision 1.10 1998/08/21 14:08:40 pierre
  926. + TEST_FUNCRET now default (old code removed)
  927. works also for m68k (at least compiles)
  928. Revision 1.9 1998/08/20 09:26:37 pierre
  929. + funcret setting in underproc testing
  930. compile with _dTEST_FUNCRET
  931. Revision 1.8 1998/08/10 14:49:48 peter
  932. + localswitches, moduleswitches, globalswitches splitting
  933. Revision 1.7 1998/07/30 13:30:33 florian
  934. * final implemenation of exception support, maybe it needs
  935. some fixes :)
  936. Revision 1.6 1998/07/26 21:58:57 florian
  937. + better support for switch $H
  938. + index access to ansi strings added
  939. + assigment of data (records/arrays) containing ansi strings
  940. Revision 1.5 1998/07/24 22:16:54 florian
  941. * internal error 10 together with array access fixed. I hope
  942. that's the final fix.
  943. Revision 1.4 1998/06/11 13:58:45 peter
  944. * fixed too long line
  945. Revision 1.3 1998/06/09 16:01:35 pierre
  946. + added procedure directive parsing for procvars
  947. (accepted are popstack cdecl and pascal)
  948. + added C vars with the following syntax
  949. var C calias 'true_c_name';(can be followed by external)
  950. reason is that you must add the Cprefix
  951. which is target dependent
  952. Revision 1.2 1998/06/08 13:13:34 pierre
  953. + temporary variables now in temp_gen.pas unit
  954. because it is processor independent
  955. * mppc68k.bat modified to undefine i386 and support_mmx
  956. (which are defaults for i386)
  957. Revision 1.1 1998/06/05 17:44:12 peter
  958. * splitted cgi386
  959. }