cg68kld.pas 22 KB

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