cg68kld.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  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. implementation
  36. uses
  37. cobjects,verbose,globals,
  38. symtable,aasm,types,
  39. hcodegen,temp_gen,pass_2,
  40. cga68k,tgen68k;
  41. {*****************************************************************************
  42. SecondLoad
  43. *****************************************************************************}
  44. procedure secondload(var p : ptree);
  45. var
  46. hregister : tregister;
  47. i : longint;
  48. symtabletype: tsymtabletype;
  49. hp : preference;
  50. begin
  51. simple_loadn:=true;
  52. reset_reference(p^.location.reference);
  53. case p^.symtableentry^.typ of
  54. { this is only for toasm and toaddr }
  55. absolutesym :
  56. begin
  57. stringdispose(p^.location.reference.symbol);
  58. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  59. if p^.symtableentry^.owner^.symtabletype=unitsymtable then
  60. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  61. end;
  62. varsym :
  63. begin
  64. hregister:=R_NO;
  65. symtabletype:=p^.symtable^.symtabletype;
  66. { in case it is a register variable: }
  67. { we simply set the location to the }
  68. { correct register. }
  69. if pvarsym(p^.symtableentry)^.reg<>R_NO then
  70. begin
  71. p^.location.loc:=LOC_CREGISTER;
  72. p^.location.register:=pvarsym(p^.symtableentry)^.reg;
  73. unused:=unused-[pvarsym(p^.symtableentry)^.reg];
  74. end
  75. else
  76. begin
  77. { --------------------- LOCAL AND TEMP VARIABLES ------------- }
  78. if (symtabletype=parasymtable) or (symtabletype=localsymtable) then
  79. begin
  80. p^.location.reference.base:=procinfo.framepointer;
  81. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  82. if (symtabletype=localsymtable) then
  83. p^.location.reference.offset:=-p^.location.reference.offset;
  84. if (symtabletype=parasymtable) then
  85. inc(p^.location.reference.offset,p^.symtable^.call_offset);
  86. if (lexlevel>(p^.symtable^.symtablelevel)) then
  87. begin
  88. hregister:=getaddressreg;
  89. { make a reference }
  90. new(hp);
  91. reset_reference(hp^);
  92. hp^.offset:=procinfo.framepointer_offset;
  93. hp^.base:=procinfo.framepointer;
  94. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hregister)));
  95. simple_loadn:=false;
  96. i:=lexlevel-1;
  97. while i>(p^.symtable^.symtablelevel) do
  98. begin
  99. { make a reference }
  100. new(hp);
  101. reset_reference(hp^);
  102. hp^.offset:=8;
  103. hp^.base:=hregister;
  104. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hregister)));
  105. dec(i);
  106. end;
  107. p^.location.reference.base:=hregister;
  108. end;
  109. end
  110. { --------------------- END OF LOCAL AND TEMP VARS ---------------- }
  111. else
  112. case symtabletype of
  113. unitsymtable,globalsymtable,
  114. staticsymtable : begin
  115. stringdispose(p^.location.reference.symbol);
  116. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  117. if symtabletype=unitsymtable then
  118. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  119. end;
  120. objectsymtable : begin
  121. if (pvarsym(p^.symtableentry)^.properties and sp_static)<>0 then
  122. begin
  123. stringdispose(p^.location.reference.symbol);
  124. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  125. if p^.symtable^.defowner^.owner^.symtabletype=unitsymtable then
  126. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  127. end
  128. else
  129. begin
  130. p^.location.reference.base:=R_A5;
  131. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  132. end;
  133. end;
  134. withsymtable : begin
  135. hregister:=getaddressreg;
  136. p^.location.reference.base:=hregister;
  137. { make a reference }
  138. new(hp);
  139. reset_reference(hp^);
  140. hp^.offset:=p^.symtable^.datasize;
  141. hp^.base:=procinfo.framepointer;
  142. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hregister)));
  143. p^.location.reference.offset:=
  144. pvarsym(p^.symtableentry)^.address;
  145. end;
  146. end;
  147. { in case call by reference, then calculate: }
  148. if (pvarsym(p^.symtableentry)^.varspez=vs_var) or
  149. ((pvarsym(p^.symtableentry)^.varspez=vs_const) and
  150. dont_copy_const_param(pvarsym(p^.symtableentry)^.definition)) then
  151. begin
  152. simple_loadn:=false;
  153. if hregister=R_NO then
  154. hregister:=getaddressreg;
  155. { ADDED FOR OPEN ARRAY SUPPORT. }
  156. if (p^.location.reference.base=procinfo.framepointer) then
  157. begin
  158. highframepointer:=p^.location.reference.base;
  159. highoffset:=p^.location.reference.offset;
  160. end
  161. else
  162. begin
  163. highframepointer:=R_A1;
  164. highoffset:=p^.location.reference.offset;
  165. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,
  166. p^.location.reference.base,R_A1)));
  167. end;
  168. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),
  169. hregister)));
  170. { END ADDITION }
  171. clear_reference(p^.location.reference);
  172. p^.location.reference.base:=hregister;
  173. end;
  174. { should be dereferenced later (FK)
  175. if (pvarsym(p^.symtableentry)^.definition^.deftype=objectdef) and
  176. ((pobjectdef(pvarsym(p^.symtableentry)^.definition)^.options and oois_class)<>0) then
  177. begin
  178. simple_loadn:=false;
  179. if hregister=R_NO then
  180. hregister:=getaddressreg;
  181. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),
  182. hregister)));
  183. clear_reference(p^.location.reference);
  184. p^.location.reference.base:=hregister;
  185. end;
  186. }
  187. end;
  188. end;
  189. procsym:
  190. begin
  191. {!!!!! Be aware, work on virtual methods too }
  192. stringdispose(p^.location.reference.symbol);
  193. p^.location.reference.symbol:=
  194. stringdup(pprocsym(p^.symtableentry)^.definition^.mangledname);
  195. if p^.symtable^.symtabletype=unitsymtable then
  196. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  197. end;
  198. typedconstsym :
  199. begin
  200. stringdispose(p^.location.reference.symbol);
  201. p^.location.reference.symbol:=stringdup(p^.symtableentry^.mangledname);
  202. if p^.symtable^.symtabletype=unitsymtable then
  203. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  204. end;
  205. else internalerror(4);
  206. end;
  207. end;
  208. {*****************************************************************************
  209. SecondAssignment
  210. *****************************************************************************}
  211. procedure secondassignment(var p : ptree);
  212. var
  213. opsize : topsize;
  214. withresult : boolean;
  215. otlabel,hlabel,oflabel : plabel;
  216. hregister : tregister;
  217. loc : tloc;
  218. begin
  219. otlabel:=truelabel;
  220. oflabel:=falselabel;
  221. getlabel(truelabel);
  222. getlabel(falselabel);
  223. withresult:=false;
  224. { calculate left sides }
  225. secondpass(p^.left);
  226. case p^.left^.location.loc of
  227. LOC_REFERENCE : begin
  228. { in case left operator uses too many registers }
  229. { but to few are free then LEA }
  230. if (p^.left^.location.reference.base<>R_NO) and
  231. (p^.left^.location.reference.index<>R_NO) and
  232. (usableaddress<p^.right^.registers32) then
  233. begin
  234. del_reference(p^.left^.location.reference);
  235. hregister:=getaddressreg;
  236. exprasmlist^.concat(new(pai68k,op_ref_reg(A_LEA,S_L,newreference(
  237. p^.left^.location.reference),
  238. hregister)));
  239. clear_reference(p^.left^.location.reference);
  240. p^.left^.location.reference.base:=hregister;
  241. p^.left^.location.reference.index:=R_NO;
  242. end;
  243. loc:=LOC_REFERENCE;
  244. end;
  245. LOC_CREGISTER : loc:=LOC_CREGISTER;
  246. else
  247. begin
  248. CGMessage(cg_e_illegal_expression);
  249. exit;
  250. end;
  251. end;
  252. { lets try to optimize this (PM) }
  253. { define a dest_loc that is the location }
  254. { and a ptree to verify that it is the right }
  255. { place to insert it }
  256. {$ifdef test_dest_loc}
  257. if (aktexprlevel<4) then
  258. begin
  259. dest_loc_known:=true;
  260. dest_loc:=p^.left^.location;
  261. dest_loc_tree:=p^.right;
  262. end;
  263. {$endif test_dest_loc}
  264. if (p^.right^.treetype=realconstn) then
  265. begin
  266. if p^.left^.resulttype^.deftype=floatdef then
  267. begin
  268. case pfloatdef(p^.left^.resulttype)^.typ of
  269. s32real : p^.right^.realtyp:=ait_real_32bit;
  270. s64real : p^.right^.realtyp:=ait_real_64bit;
  271. s80real : p^.right^.realtyp:=ait_real_extended;
  272. { what about f32bit and s64bit }
  273. end;
  274. end;
  275. end;
  276. secondpass(p^.right);
  277. {$ifdef test_dest_loc}
  278. dest_loc_known:=false;
  279. if in_dest_loc then
  280. begin
  281. truelabel:=otlabel;
  282. falselabel:=oflabel;
  283. in_dest_loc:=false;
  284. exit;
  285. end;
  286. {$endif test_dest_loc}
  287. if p^.left^.resulttype^.deftype=stringdef then
  288. begin
  289. { we do not need destination anymore }
  290. del_reference(p^.left^.location.reference);
  291. { only source if withresult is set }
  292. if not(withresult) then
  293. del_reference(p^.right^.location.reference);
  294. loadstring(p);
  295. ungetiftemp(p^.right^.location.reference);
  296. end
  297. else case p^.right^.location.loc of
  298. LOC_REFERENCE,
  299. LOC_MEM : begin
  300. { handle ordinal constants trimmed }
  301. if (p^.right^.treetype in [ordconstn,fixconstn]) or
  302. (loc=LOC_CREGISTER) then
  303. begin
  304. case p^.left^.resulttype^.size of
  305. 1 : opsize:=S_B;
  306. 2 : opsize:=S_W;
  307. 4 : opsize:=S_L;
  308. end;
  309. if loc=LOC_CREGISTER then
  310. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,
  311. newreference(p^.right^.location.reference),
  312. p^.left^.location.register)))
  313. else
  314. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,opsize,
  315. p^.right^.location.reference.offset,
  316. newreference(p^.left^.location.reference))));
  317. {exprasmlist^.concat(new(pai68k,op_const_loc(A_MOV,opsize,
  318. p^.right^.location.reference.offset,
  319. p^.left^.location)));}
  320. end
  321. else
  322. begin
  323. concatcopy(p^.right^.location.reference,
  324. p^.left^.location.reference,p^.left^.resulttype^.size,
  325. withresult);
  326. ungetiftemp(p^.right^.location.reference);
  327. end;
  328. end;
  329. LOC_REGISTER,
  330. LOC_CREGISTER : begin
  331. case p^.right^.resulttype^.size of
  332. 1 : opsize:=S_B;
  333. 2 : opsize:=S_W;
  334. 4 : opsize:=S_L;
  335. end;
  336. { simplified with op_reg_loc }
  337. if loc=LOC_CREGISTER then
  338. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,opsize,
  339. p^.right^.location.register,
  340. p^.left^.location.register)))
  341. else
  342. exprasmlist^.concat(new(pai68k,op_reg_ref(A_MOVE,opsize,
  343. p^.right^.location.register,
  344. newreference(p^.left^.location.reference))));
  345. {exprasmlist^.concat(new(pai68k,op_reg_loc(A_MOV,opsize,
  346. p^.right^.location.register,
  347. p^.left^.location))); }
  348. end;
  349. LOC_FPU : begin
  350. if loc<>LOC_REFERENCE then
  351. internalerror(10010)
  352. else
  353. floatstore(pfloatdef(p^.left^.resulttype)^.typ,
  354. p^.right^.location,p^.left^.location.reference);
  355. end;
  356. LOC_JUMP : begin
  357. getlabel(hlabel);
  358. emitl(A_LABEL,truelabel);
  359. if loc=LOC_CREGISTER then
  360. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_B,
  361. 1,p^.left^.location.register)))
  362. else
  363. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_B,
  364. 1,newreference(p^.left^.location.reference))));
  365. {exprasmlist^.concat(new(pai68k,op_const_loc(A_MOV,S_B,
  366. 1,p^.left^.location)));}
  367. emitl(A_JMP,hlabel);
  368. emitl(A_LABEL,falselabel);
  369. if loc=LOC_CREGISTER then
  370. exprasmlist^.concat(new(pai68k,op_reg(A_CLR,S_B,
  371. p^.left^.location.register)))
  372. else
  373. exprasmlist^.concat(new(pai68k,op_const_ref(A_MOVE,S_B,
  374. 0,newreference(p^.left^.location.reference))));
  375. emitl(A_LABEL,hlabel);
  376. end;
  377. LOC_FLAGS : begin
  378. if loc=LOC_CREGISTER then
  379. begin
  380. exprasmlist^.concat(new(pai68k,op_reg(flag_2_set[p^.right^.location.resflags],S_B,
  381. p^.left^.location.register)));
  382. exprasmlist^.concat(new(pai68k,op_reg(A_NEG,S_B,p^.left^.location.register)));
  383. end
  384. else
  385. begin
  386. exprasmlist^.concat(new(pai68k,op_ref(flag_2_set[p^.right^.location.resflags],S_B,
  387. newreference(p^.left^.location.reference))));
  388. exprasmlist^.concat(new(pai68k,op_ref(A_NEG,S_B,newreference(p^.left^.location.reference))));
  389. end;
  390. end;
  391. end;
  392. truelabel:=otlabel;
  393. falselabel:=oflabel;
  394. end;
  395. {*****************************************************************************
  396. SecondFuncRetN
  397. *****************************************************************************}
  398. procedure secondfuncret(var p : ptree);
  399. var
  400. hr : tregister;
  401. hp : preference;
  402. pp : pprocinfo;
  403. hr_valid : boolean;
  404. begin
  405. clear_reference(p^.location.reference);
  406. hr_valid:=false;
  407. { !!!!!!! }
  408. (* if @procinfo<>pprocinfo(p^.funcretprocinfo) then
  409. begin
  410. hr:=getregister32;
  411. hr_valid:=false;
  412. hp:=new_reference(procinfo.framepointer,
  413. procinfo.framepointer_offset);
  414. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hr)));
  415. pp:=procinfo.parent;
  416. { walk up the stack frame }
  417. while pp<>pprocinfo(p^.funcretprocinfo) do
  418. begin
  419. hp:=new_reference(hr,
  420. pp^.framepointer_offset);
  421. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,hp,hr)));
  422. pp:=pp^.parent;
  423. end;
  424. p^.location.reference.base:=hr;
  425. end
  426. else *)
  427. p^.location.reference.base:=procinfo.framepointer;
  428. p^.location.reference.offset:=procinfo.retoffset;
  429. if ret_in_param(p^.retdef) then
  430. begin
  431. if not hr_valid then
  432. hr:=getregister32;
  433. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),hr)));
  434. p^.location.reference.base:=hr;
  435. p^.location.reference.offset:=0;
  436. end;
  437. end;
  438. end.
  439. {
  440. $Log$
  441. Revision 1.2 1998-09-17 09:42:27 peter
  442. + pass_2 for cg386
  443. * Message() -> CGMessage() for pass_1/pass_2
  444. Revision 1.1 1998/09/01 09:07:09 peter
  445. * m68k fixes, splitted cg68k like cgi386
  446. }