cg68kld.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  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.13 2000-02-09 13:22:49 peter
  430. * log truncated
  431. Revision 1.12 2000/01/07 01:14:22 peter
  432. * updated copyright to 2000
  433. Revision 1.11 1999/12/22 01:01:47 peter
  434. - removed freelabel()
  435. * added undefined label detection in internal assembler, this prevents
  436. a lot of ld crashes and wrong .o files
  437. * .o files aren't written anymore if errors have occured
  438. * inlining of assembler labels is now correct
  439. Revision 1.10 1999/11/10 00:06:08 pierre
  440. * adapted to procinfo as pointer
  441. Revision 1.9 1999/09/16 23:05:51 florian
  442. * m68k compiler is again compilable (only gas writer, no assembler reader)
  443. Revision 1.8 1999/09/16 11:34:54 pierre
  444. * typo correction
  445. }