cg68kld.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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. truelabel:=otlabel;
  356. falselabel:=oflabel;
  357. end;
  358. {*****************************************************************************
  359. SecondFuncRetN
  360. *****************************************************************************}
  361. procedure secondfuncret(var p : ptree);
  362. var
  363. hr : tregister;
  364. hp : preference;
  365. pp : pprocinfo;
  366. hr_valid : boolean;
  367. begin
  368. clear_reference(p^.location.reference);
  369. hr_valid:=false;
  370. { !!!!!!! }
  371. if @procinfo<>pprocinfo(p^.funcretprocinfo) then
  372. begin
  373. hr:=getaddressreg;
  374. hr_valid:=true;
  375. hp:=new_reference(procinfo^.framepointer,
  376. procinfo^.framepointer_offset);
  377. exprasmlist^.concat(new(paicpu,op_ref_reg(A_MOVE,S_L,hp,hr)));
  378. pp:=procinfo^.parent;
  379. { walk up the stack frame }
  380. while pp<>pprocinfo(p^.funcretprocinfo) do
  381. begin
  382. hp:=new_reference(hr,
  383. pp^.framepointer_offset);
  384. exprasmlist^.concat(new(paicpu,op_ref_reg(A_MOVE,S_L,hp,hr)));
  385. pp:=pp^.parent;
  386. end;
  387. p^.location.reference.base:=hr;
  388. end
  389. else
  390. p^.location.reference.base:=procinfo^.framepointer;
  391. p^.location.reference.offset:=procinfo^.retoffset;
  392. if ret_in_param(p^.retdef) then
  393. begin
  394. if not hr_valid then
  395. { this was wrong !! PM }
  396. hr:=getaddressreg;
  397. exprasmlist^.concat(new(paicpu,op_ref_reg(A_MOVE,S_L,newreference(p^.location.reference),hr)));
  398. p^.location.reference.base:=hr;
  399. p^.location.reference.offset:=0;
  400. end;
  401. end;
  402. {*****************************************************************************
  403. SecondArrayConstruct
  404. *****************************************************************************}
  405. const
  406. vtInteger = 0;
  407. vtBoolean = 1;
  408. vtChar = 2;
  409. vtExtended = 3;
  410. vtString = 4;
  411. vtPointer = 5;
  412. vtPChar = 6;
  413. vtObject = 7;
  414. vtClass = 8;
  415. vtWideChar = 9;
  416. vtPWideChar = 10;
  417. vtAnsiString = 11;
  418. vtCurrency = 12;
  419. vtVariant = 13;
  420. vtInterface = 14;
  421. vtWideString = 15;
  422. vtInt64 = 16;
  423. procedure secondarrayconstruct(var p : ptree);
  424. begin
  425. end;
  426. end.
  427. {
  428. $Log$
  429. Revision 1.12 2000-01-07 01:14:22 peter
  430. * updated copyright to 2000
  431. Revision 1.11 1999/12/22 01:01:47 peter
  432. - removed freelabel()
  433. * added undefined label detection in internal assembler, this prevents
  434. a lot of ld crashes and wrong .o files
  435. * .o files aren't written anymore if errors have occured
  436. * inlining of assembler labels is now correct
  437. Revision 1.10 1999/11/10 00:06:08 pierre
  438. * adapted to procinfo as pointer
  439. Revision 1.9 1999/09/16 23:05:51 florian
  440. * m68k compiler is again compilable (only gas writer, no assembler reader)
  441. Revision 1.8 1999/09/16 11:34:54 pierre
  442. * typo correction
  443. Revision 1.7 1998/10/19 08:54:55 pierre
  444. * wrong stabs info corrected once again !!
  445. + variable vmt offset with vmt field only if required
  446. implemented now !!!
  447. Revision 1.6 1998/10/14 08:47:16 pierre
  448. * bugs in secondfuncret for result in subprocedures removed
  449. Revision 1.5 1998/10/14 08:08:53 pierre
  450. * following Peters remark, removed all ifdef in
  451. the systems unit enums
  452. * last bugs of cg68k removed for sysamiga
  453. (sysamiga assembles with as68k !!)
  454. Revision 1.4 1998/10/13 08:19:28 pierre
  455. + source_os is now set correctly for cross-processor compilers
  456. (tos contains all target_infos and
  457. we use CPU86 and CPU68 conditionals to
  458. get the source operating system
  459. this only works if you do not undefine
  460. the source target !!)
  461. * several cg68k memory leaks fixed
  462. + started to change the code so that it should be possible to have
  463. a complete compiler (both for m68k and i386 !!)
  464. Revision 1.3 1998/10/06 20:48:59 peter
  465. * m68k compiler compiles again
  466. Revision 1.2 1998/09/17 09:42:27 peter
  467. + pass_2 for cg386
  468. * Message() -> CGMessage() for pass_1/pass_2
  469. Revision 1.1 1998/09/01 09:07:09 peter
  470. * m68k fixes, splitted cg68k like cgi386
  471. }