cg68kld.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. Generate m68k 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 cg68kld;
  19. interface
  20. uses
  21. tree,m68k;
  22. var
  23. { this is for open arrays and strings }
  24. { but be careful, this data is in the }
  25. { generated code destroyed quick, and also }
  26. { the next call of secondload destroys this }
  27. { data }
  28. { So be careful using the informations }
  29. { provided by this variables }
  30. highframepointer : tregister;
  31. highoffset : longint;
  32. procedure secondload(var p : ptree);
  33. procedure secondassignment(var p : ptree);
  34. procedure secondfuncret(var p : ptree);
  35. procedure secondarrayconstruct(var p : ptree);
  36. implementation
  37. uses
  38. cobjects,verbose,globals,
  39. symtable,aasm,types,
  40. hcodegen,temp_gen,pass_2,
  41. cga68k,tgen68k;
  42. {*****************************************************************************
  43. SecondLoad
  44. *****************************************************************************}
  45. procedure secondload(var p : ptree);
  46. var
  47. hregister : tregister;
  48. i : longint;
  49. symtabletype: tsymtabletype;
  50. hp : preference;
  51. begin
  52. simple_loadn:=true;
  53. reset_reference(p^.location.reference);
  54. case p^.symtableentry^.typ of
  55. { this is only for toasm and toaddr }
  56. absolutesym :
  57. begin
  58. stringdispose(p^.location.reference.symbol);
  59. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  60. if p^.symtableentry^.owner^.symtabletype=unitsymtable then
  61. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  62. end;
  63. varsym :
  64. begin
  65. hregister:=R_NO;
  66. symtabletype:=p^.symtable^.symtabletype;
  67. { in case it is a register variable: }
  68. { we simply set the location to the }
  69. { correct register. }
  70. if pvarsym(p^.symtableentry)^.reg<>R_NO then
  71. begin
  72. p^.location.loc:=LOC_CREGISTER;
  73. p^.location.register:=pvarsym(p^.symtableentry)^.reg;
  74. unused:=unused-[pvarsym(p^.symtableentry)^.reg];
  75. end
  76. else
  77. begin
  78. { --------------------- LOCAL AND TEMP VARIABLES ------------- }
  79. if (symtabletype=parasymtable) or (symtabletype=localsymtable) then
  80. begin
  81. p^.location.reference.base:=procinfo.framepointer;
  82. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  83. if (symtabletype=localsymtable) then
  84. p^.location.reference.offset:=-p^.location.reference.offset;
  85. if (symtabletype=parasymtable) then
  86. inc(p^.location.reference.offset,p^.symtable^.call_offset);
  87. if (lexlevel>(p^.symtable^.symtablelevel)) then
  88. begin
  89. hregister:=getaddressreg;
  90. { make a reference }
  91. new(hp);
  92. reset_reference(hp^);
  93. hp^.offset:=procinfo.framepointer_offset;
  94. hp^.base:=procinfo.framepointer;
  95. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hregister)));
  96. simple_loadn:=false;
  97. i:=lexlevel-1;
  98. while i>(p^.symtable^.symtablelevel) do
  99. begin
  100. { make a reference }
  101. new(hp);
  102. reset_reference(hp^);
  103. hp^.offset:=8;
  104. hp^.base:=hregister;
  105. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hregister)));
  106. dec(i);
  107. end;
  108. p^.location.reference.base:=hregister;
  109. end;
  110. end
  111. { --------------------- END OF LOCAL AND TEMP VARS ---------------- }
  112. else
  113. case symtabletype of
  114. unitsymtable,globalsymtable,
  115. staticsymtable : begin
  116. stringdispose(p^.location.reference.symbol);
  117. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  118. if symtabletype=unitsymtable then
  119. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  120. end;
  121. objectsymtable : begin
  122. if (pvarsym(p^.symtableentry)^.properties and sp_static)<>0 then
  123. begin
  124. stringdispose(p^.location.reference.symbol);
  125. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  126. if p^.symtable^.defowner^.owner^.symtabletype=unitsymtable then
  127. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  128. end
  129. else
  130. begin
  131. p^.location.reference.base:=R_A5;
  132. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  133. end;
  134. end;
  135. withsymtable : begin
  136. hregister:=getaddressreg;
  137. p^.location.reference.base:=hregister;
  138. { make a reference }
  139. new(hp);
  140. reset_reference(hp^);
  141. hp^.offset:=p^.symtable^.datasize;
  142. hp^.base:=procinfo.framepointer;
  143. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hregister)));
  144. p^.location.reference.offset:=
  145. pvarsym(p^.symtableentry)^.address;
  146. end;
  147. end;
  148. { in case call by reference, then calculate: }
  149. if (pvarsym(p^.symtableentry)^.varspez=vs_var) or
  150. ((pvarsym(p^.symtableentry)^.varspez=vs_const) and
  151. dont_copy_const_param(pvarsym(p^.symtableentry)^.definition)) then
  152. begin
  153. simple_loadn:=false;
  154. if hregister=R_NO then
  155. hregister:=getaddressreg;
  156. { ADDED FOR OPEN ARRAY SUPPORT. }
  157. if (p^.location.reference.base=procinfo.framepointer) then
  158. begin
  159. highframepointer:=p^.location.reference.base;
  160. highoffset:=p^.location.reference.offset;
  161. end
  162. else
  163. begin
  164. highframepointer:=R_A1;
  165. highoffset:=p^.location.reference.offset;
  166. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  167. p^.location.reference.base,R_A1)));
  168. end;
  169. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),
  170. hregister)));
  171. { END ADDITION }
  172. clear_reference(p^.location.reference);
  173. p^.location.reference.base:=hregister;
  174. end;
  175. { should be dereferenced later (FK)
  176. if (pvarsym(p^.symtableentry)^.definition^.deftype=objectdef) and
  177. ((pobjectdef(pvarsym(p^.symtableentry)^.definition)^.options and oo_is_class)<>0) then
  178. begin
  179. simple_loadn:=false;
  180. if hregister=R_NO then
  181. hregister:=getaddressreg;
  182. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),
  183. hregister)));
  184. clear_reference(p^.location.reference);
  185. p^.location.reference.base:=hregister;
  186. end;
  187. }
  188. end;
  189. end;
  190. procsym:
  191. begin
  192. {!!!!! Be aware, work on virtual methods too }
  193. stringdispose(p^.location.reference.symbol);
  194. p^.location.reference.symbol:=
  195. stringdup(pprocsym(p^.symtableentry)^.definition^.mangledname);
  196. if p^.symtable^.symtabletype=unitsymtable then
  197. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  198. end;
  199. typedconstsym :
  200. begin
  201. stringdispose(p^.location.reference.symbol);
  202. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  203. if p^.symtable^.symtabletype=unitsymtable then
  204. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  205. end;
  206. else internalerror(4);
  207. end;
  208. end;
  209. {*****************************************************************************
  210. SecondAssignment
  211. *****************************************************************************}
  212. procedure secondassignment(var p : ptree);
  213. var
  214. opsize : topsize;
  215. withresult : boolean;
  216. otlabel,hlabel,oflabel : plabel;
  217. hregister : tregister;
  218. loc : tloc;
  219. begin
  220. otlabel:=truelabel;
  221. oflabel:=falselabel;
  222. getlabel(truelabel);
  223. getlabel(falselabel);
  224. withresult:=false;
  225. { calculate left sides }
  226. secondpass(p^.left);
  227. case p^.left^.location.loc of
  228. LOC_REFERENCE : begin
  229. { in case left operator uses too many registers }
  230. { but to few are free then LEA }
  231. if (p^.left^.location.reference.base<>R_NO) and
  232. (p^.left^.location.reference.index<>R_NO) and
  233. (usableaddress<p^.right^.registers32) then
  234. begin
  235. del_reference(p^.left^.location.reference);
  236. hregister:=getaddressreg;
  237. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(
  238. p^.left^.location.reference),
  239. hregister)));
  240. clear_reference(p^.left^.location.reference);
  241. p^.left^.location.reference.base:=hregister;
  242. p^.left^.location.reference.index:=R_NO;
  243. end;
  244. loc:=LOC_REFERENCE;
  245. end;
  246. LOC_CREGISTER : loc:=LOC_CREGISTER;
  247. else
  248. begin
  249. CGMessage(cg_e_illegal_expression);
  250. exit;
  251. end;
  252. end;
  253. { lets try to optimize this (PM) }
  254. { define a dest_loc that is the location }
  255. { and a ptree to verify that it is the right }
  256. { place to insert it }
  257. {$ifdef test_dest_loc}
  258. if (aktexprlevel<4) then
  259. begin
  260. dest_loc_known:=true;
  261. dest_loc:=p^.left^.location;
  262. dest_loc_tree:=p^.right;
  263. end;
  264. {$endif test_dest_loc}
  265. if (p^.right^.treetype=realconstn) then
  266. begin
  267. if p^.left^.resulttype^.deftype=floatdef then
  268. begin
  269. case pfloatdef(p^.left^.resulttype)^.typ of
  270. s32real : p^.right^.realtyp:=ait_real_32bit;
  271. s64real : p^.right^.realtyp:=ait_real_64bit;
  272. s80real : p^.right^.realtyp:=ait_real_extended;
  273. { what about f32bit and s64bit }
  274. end;
  275. end;
  276. end;
  277. secondpass(p^.right);
  278. {$ifdef test_dest_loc}
  279. dest_loc_known:=false;
  280. if in_dest_loc then
  281. begin
  282. truelabel:=otlabel;
  283. falselabel:=oflabel;
  284. in_dest_loc:=false;
  285. exit;
  286. end;
  287. {$endif test_dest_loc}
  288. if p^.left^.resulttype^.deftype=stringdef then
  289. begin
  290. { we do not need destination anymore }
  291. del_reference(p^.left^.location.reference);
  292. { only source if withresult is set }
  293. if not(withresult) then
  294. del_reference(p^.right^.location.reference);
  295. loadstring(p);
  296. ungetiftemp(p^.right^.location.reference);
  297. end
  298. else case p^.right^.location.loc of
  299. LOC_REFERENCE,
  300. LOC_MEM : begin
  301. { handle ordinal constants trimmed }
  302. if (p^.right^.treetype in [ordconstn,fixconstn]) or
  303. (loc=LOC_CREGISTER) then
  304. begin
  305. case p^.left^.resulttype^.size of
  306. 1 : opsize:=S_B;
  307. 2 : opsize:=S_W;
  308. 4 : opsize:=S_L;
  309. end;
  310. if loc=LOC_CREGISTER then
  311. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,
  312. newreference(p^.right^.location.reference),
  313. p^.left^.location.register)))
  314. else
  315. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,opsize,
  316. p^.right^.location.reference.offset,
  317. newreference(p^.left^.location.reference))));
  318. {exprasmlist^.concat(new(pai68k,op_const_loc(A_MOV,opsize,
  319. p^.right^.location.reference.offset,
  320. p^.left^.location)));}
  321. end
  322. else
  323. begin
  324. concatcopy(p^.right^.location.reference,
  325. p^.left^.location.reference,p^.left^.resulttype^.size,
  326. withresult);
  327. ungetiftemp(p^.right^.location.reference);
  328. end;
  329. end;
  330. LOC_REGISTER,
  331. LOC_CREGISTER : begin
  332. case p^.right^.resulttype^.size of
  333. 1 : opsize:=S_B;
  334. 2 : opsize:=S_W;
  335. 4 : opsize:=S_L;
  336. end;
  337. { simplified with op_reg_loc }
  338. if loc=LOC_CREGISTER then
  339. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,opsize,
  340. p^.right^.location.register,
  341. p^.left^.location.register)))
  342. else
  343. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,opsize,
  344. p^.right^.location.register,
  345. newreference(p^.left^.location.reference))));
  346. {exprasmlist^.concat(new(pai68k,op_reg_loc(A_MOV,opsize,
  347. p^.right^.location.register,
  348. p^.left^.location))); }
  349. end;
  350. LOC_FPU : begin
  351. if loc<>LOC_REFERENCE then
  352. internalerror(10010)
  353. else
  354. floatstore(pfloatdef(p^.left^.resulttype)^.typ,
  355. p^.right^.location,p^.left^.location.reference);
  356. end;
  357. LOC_JUMP : begin
  358. getlabel(hlabel);
  359. emitl(A_LABEL,truelabel);
  360. if loc=LOC_CREGISTER then
  361. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_B,
  362. 1,p^.left^.location.register)))
  363. else
  364. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_B,
  365. 1,newreference(p^.left^.location.reference))));
  366. {exprasmlist^.concat(new(pai68k,op_const_loc(A_MOV,S_B,
  367. 1,p^.left^.location)));}
  368. emitl(A_JMP,hlabel);
  369. emitl(A_LABEL,falselabel);
  370. if loc=LOC_CREGISTER then
  371. exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_B,
  372. p^.left^.location.register)))
  373. else
  374. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_B,
  375. 0,newreference(p^.left^.location.reference))));
  376. emitl(A_LABEL,hlabel);
  377. end;
  378. LOC_FLAGS : begin
  379. if loc=LOC_CREGISTER then
  380. begin
  381. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[p^.right^.location.resflags],S_B,
  382. p^.left^.location.register)));
  383. exprasmlist^.concat(new(pai68k,op_reg(A_NEG,S_B,p^.left^.location.register)));
  384. end
  385. else
  386. begin
  387. exprasmlist^.concat(new(pai68k,op_ref(flag_2_set[p^.right^.location.resflags],S_B,
  388. newreference(p^.left^.location.reference))));
  389. exprasmlist^.concat(new(pai68k,op_ref(A_NEG,S_B,newreference(p^.left^.location.reference))));
  390. end;
  391. end;
  392. end;
  393. freelabel(truelabel);
  394. freelabel(falselabel);
  395. truelabel:=otlabel;
  396. falselabel:=oflabel;
  397. end;
  398. {*****************************************************************************
  399. SecondFuncRetN
  400. *****************************************************************************}
  401. procedure secondfuncret(var p : ptree);
  402. var
  403. hr : tregister;
  404. hp : preference;
  405. pp : pprocinfo;
  406. hr_valid : boolean;
  407. begin
  408. clear_reference(p^.location.reference);
  409. hr_valid:=false;
  410. { !!!!!!! }
  411. if @procinfo<>pprocinfo(p^.funcretprocinfo) then
  412. begin
  413. hr:=getaddressreg;
  414. hr_valid:=true;
  415. hp:=new_reference(procinfo.framepointer,
  416. procinfo.framepointer_offset);
  417. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hr)));
  418. pp:=procinfo.parent;
  419. { walk up the stack frame }
  420. while pp<>pprocinfo(p^.funcretprocinfo) do
  421. begin
  422. hp:=new_reference(hr,
  423. pp^.framepointer_offset);
  424. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hr)));
  425. pp:=pp^.parent;
  426. end;
  427. p^.location.reference.base:=hr;
  428. end
  429. else
  430. p^.location.reference.base:=procinfo.framepointer;
  431. p^.location.reference.offset:=procinfo.retoffset;
  432. if ret_in_param(p^.retdef) then
  433. begin
  434. if not hr_valid then
  435. { this was wrong !! PM }
  436. hr:=getaddressreg;
  437. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),hr)));
  438. p^.location.reference.base:=hr;
  439. p^.location.reference.offset:=0;
  440. end;
  441. end;
  442. {*****************************************************************************
  443. SecondArrayConstruct
  444. *****************************************************************************}
  445. const
  446. vtInteger = 0;
  447. vtBoolean = 1;
  448. vtChar = 2;
  449. vtExtended = 3;
  450. vtString = 4;
  451. vtPointer = 5;
  452. vtPChar = 6;
  453. vtObject = 7;
  454. vtClass = 8;
  455. vtWideChar = 9;
  456. vtPWideChar = 10;
  457. vtAnsiString = 11;
  458. vtCurrency = 12;
  459. vtVariant = 13;
  460. vtInterface = 14;
  461. vtWideString = 15;
  462. vtInt64 = 16;
  463. procedure secondarrayconstruct(var p : ptree);
  464. begin
  465. end;
  466. end.
  467. {
  468. $Log$
  469. Revision 1.7 1998-10-19 08:54:55 pierre
  470. * wrong stabs info corrected once again !!
  471. + variable vmt offset with vmt field only if required
  472. implemented now !!!
  473. Revision 1.6 1998/10/14 08:47:16 pierre
  474. * bugs in secondfuncret for result in subprocedures removed
  475. Revision 1.5 1998/10/14 08:08:53 pierre
  476. * following Peters remark, removed all ifdef in
  477. the systems unit enums
  478. * last bugs of cg68k removed for sysamiga
  479. (sysamiga assembles with as68k !!)
  480. Revision 1.4 1998/10/13 08:19:28 pierre
  481. + source_os is now set correctly for cross-processor compilers
  482. (tos contains all target_infos and
  483. we use CPU86 and CPU68 conditionnals to
  484. get the source operating system
  485. this only works if you do not undefine
  486. the source target !!)
  487. * several cg68k memory leaks fixed
  488. + started to change the code so that it should be possible to have
  489. a complete compiler (both for m68k and i386 !!)
  490. Revision 1.3 1998/10/06 20:48:59 peter
  491. * m68k compiler compiles again
  492. Revision 1.2 1998/09/17 09:42:27 peter
  493. + pass_2 for cg386
  494. * Message() -> CGMessage() for pass_1/pass_2
  495. Revision 1.1 1998/09/01 09:07:09 peter
  496. * m68k fixes, splitted cg68k like cgi386
  497. }