cg68kld.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  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 oois_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:=getregister32;
  414. hr_valid:=false;
  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. hr:=getregister32;
  436. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),hr)));
  437. p^.location.reference.base:=hr;
  438. p^.location.reference.offset:=0;
  439. end;
  440. end;
  441. {*****************************************************************************
  442. SecondArrayConstruct
  443. *****************************************************************************}
  444. const
  445. vtInteger = 0;
  446. vtBoolean = 1;
  447. vtChar = 2;
  448. vtExtended = 3;
  449. vtString = 4;
  450. vtPointer = 5;
  451. vtPChar = 6;
  452. vtObject = 7;
  453. vtClass = 8;
  454. vtWideChar = 9;
  455. vtPWideChar = 10;
  456. vtAnsiString = 11;
  457. vtCurrency = 12;
  458. vtVariant = 13;
  459. vtInterface = 14;
  460. vtWideString = 15;
  461. vtInt64 = 16;
  462. procedure secondarrayconstruct(var p : ptree);
  463. begin
  464. end;
  465. end.
  466. {
  467. $Log$
  468. Revision 1.4 1998-10-13 08:19:28 pierre
  469. + source_os is now set correctly for cross-processor compilers
  470. (tos contains all target_infos and
  471. we use CPU86 and CPU68 conditionnals to
  472. get the source operating system
  473. this only works if you do not undefine
  474. the source target !!)
  475. * several cg68k memory leaks fixed
  476. + started to change the code so that it should be possible to have
  477. a complete compiler (both for m68k and i386 !!)
  478. Revision 1.3 1998/10/06 20:48:59 peter
  479. * m68k compiler compiles again
  480. Revision 1.2 1998/09/17 09:42:27 peter
  481. + pass_2 for cg386
  482. * Message() -> CGMessage() for pass_1/pass_2
  483. Revision 1.1 1998/09/01 09:07:09 peter
  484. * m68k fixes, splitted cg68k like cgi386
  485. }