ag68kmot.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. {
  2. $Id$
  3. Copyright (c) 1998 by the FPC development team
  4. This unit implements an asmoutput class for MOTOROLA syntax with
  5. Motorola 68000 (recognized by the Amiga Assembler and Charlie Gibbs's
  6. A68k)
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. unit ag68kmot;
  21. interface
  22. uses aasm,assemble;
  23. type
  24. pm68kmotasmlist=^tm68kmotasmlist;
  25. tm68kmotasmlist = object(tasmlist)
  26. procedure WriteTree(p:paasmoutput);virtual;
  27. procedure WriteAsmList;virtual;
  28. end;
  29. implementation
  30. uses
  31. dos,globals,systems,cobjects,m68k,
  32. strings,files,verbose
  33. {$ifdef GDB}
  34. ,gdb
  35. {$endif GDB}
  36. ;
  37. const
  38. line_length = 70;
  39. function double2str(d : double) : string;
  40. var
  41. hs : string;
  42. begin
  43. str(d,hs);
  44. double2str:=hs;
  45. end;
  46. function comp2str(d : bestreal) : string;
  47. type
  48. pdouble = ^double;
  49. var
  50. c : comp;
  51. dd : pdouble;
  52. begin
  53. {$ifdef TP}
  54. c:=d;
  55. {$else}
  56. c:=comp(d);
  57. {$endif}
  58. dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
  59. comp2str:=double2str(dd^);
  60. end;
  61. function getreferencestring(const ref : treference) : string;
  62. var
  63. s : string;
  64. begin
  65. s:='';
  66. if ref.isintvalue then
  67. s:='#'+tostr(ref.offset)
  68. else
  69. with ref do
  70. begin
  71. if (index=R_NO) and (base=R_NO) and (direction=dir_none) then
  72. begin
  73. if assigned(symbol) then
  74. begin
  75. s:=s+symbol^;
  76. if offset<0 then
  77. s:=s+tostr(offset)
  78. else
  79. if (offset>0) then
  80. s:=s+'+'+tostr(offset);
  81. end
  82. else
  83. begin
  84. { direct memory addressing }
  85. s:=s+'('+tostr(offset)+').l';
  86. end;
  87. end
  88. else
  89. begin
  90. if assigned(symbol) then
  91. s:=s+symbol^;
  92. if offset<0 then
  93. s:=s+tostr(offset)
  94. else
  95. if (offset>0) then
  96. begin
  97. if (symbol=nil) then s:=tostr(offset)
  98. else s:=s+'+'+tostr(offset);
  99. end;
  100. if (index<>R_NO) and (base=R_NO) and (direction=dir_none) then
  101. begin
  102. if (scalefactor = 1) or (scalefactor = 0) then
  103. begin
  104. if offset = 0 then
  105. s:=s+'0(,'+mot_reg2str[index]+'.l)'
  106. else
  107. s:=s+'(,'+mot_reg2str[index]+'.l)';
  108. end
  109. else
  110. begin
  111. if offset = 0 then
  112. s:=s+'0(,'+mot_reg2str[index]+'.l*'+tostr(scalefactor)+')'
  113. else
  114. s:=s+'(,'+mot_reg2str[index]+'.l*'+tostr(scalefactor)+')';
  115. end
  116. end
  117. else
  118. if (index=R_NO) and (base<>R_NO) and (direction=dir_inc) then
  119. begin
  120. if (scalefactor = 1) or (scalefactor = 0) then
  121. s:=s+'('+mot_reg2str[base]+')+'
  122. else
  123. InternalError(10002);
  124. end
  125. else
  126. if (index=R_NO) and (base<>R_NO) and (direction=dir_dec) then
  127. begin
  128. if (scalefactor = 1) or (scalefactor = 0) then
  129. s:=s+'-('+mot_reg2str[base]+')'
  130. else
  131. InternalError(10003);
  132. end
  133. else
  134. if (index=R_NO) and (base<>R_NO) and (direction=dir_none) then
  135. begin
  136. s:=s+'('+mot_reg2str[base]+')';
  137. end
  138. else
  139. if (index<>R_NO) and (base<>R_NO) and (direction=dir_none) then
  140. begin
  141. if (scalefactor = 1) or (scalefactor = 0) then
  142. begin
  143. if offset = 0 then
  144. s:=s+'0('+mot_reg2str[base]+','+mot_reg2str[index]+'.l)'
  145. else
  146. s:=s+'('+mot_reg2str[base]+','+mot_reg2str[index]+'.l)';
  147. end
  148. else
  149. begin
  150. if offset = 0 then
  151. s:=s+'0('+mot_reg2str[base]+','+mot_reg2str[index]+'.l*'+tostr(scalefactor)+')'
  152. else
  153. s:=s+'('+mot_reg2str[base]+','+mot_reg2str[index]+'.l*'+tostr(scalefactor)+')';
  154. end
  155. end
  156. { if this is not a symbol, and is not in the above, then there is an error }
  157. else
  158. if NOT assigned(symbol) then
  159. InternalError(10004);
  160. end; { endif }
  161. end; { end with }
  162. getreferencestring:=s;
  163. end;
  164. function getopstr(t : byte;o : pointer) : string;
  165. var
  166. hs : string;
  167. i: tregister;
  168. begin
  169. case t of
  170. top_reg : getopstr:=mot_reg2str[tregister(o)];
  171. top_reglist: begin
  172. hs:='';
  173. for i:=R_NO to R_FPSR do
  174. begin
  175. if i in tregisterlist(o^) then
  176. hs:=hs+mot_reg2str[i]+'/';
  177. end;
  178. delete(hs,length(hs),1);
  179. getopstr := hs;
  180. end;
  181. top_ref : getopstr:=getreferencestring(preference(o)^);
  182. top_const : getopstr:='#'+tostr(longint(o));
  183. top_symbol : begin
  184. { compare with i386 version, where this is a constant. }
  185. hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
  186. move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
  187. { inc(byte(hs[0]));}
  188. { hs[1]:='#';}
  189. if pcsymbol(o)^.offset>0 then
  190. hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
  191. else if pcsymbol(o)^.offset<0 then
  192. hs:=hs+tostr(pcsymbol(o)^.offset);
  193. getopstr:=hs;
  194. end;
  195. else internalerror(10001);
  196. end;
  197. end;
  198. function getopstr_jmp(t : byte;o : pointer) : string;
  199. var
  200. hs : string;
  201. begin
  202. case t of
  203. top_reg : getopstr_jmp:=mot_reg2str[tregister(o)];
  204. top_ref : getopstr_jmp:=getreferencestring(preference(o)^);
  205. top_const : getopstr_jmp:=tostr(longint(o));
  206. top_symbol : begin
  207. hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
  208. move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
  209. if pcsymbol(o)^.offset>0 then
  210. hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
  211. else if pcsymbol(o)^.offset<0 then
  212. hs:=hs+tostr(pcsymbol(o)^.offset);
  213. getopstr_jmp:=hs;
  214. end;
  215. else internalerror(10001);
  216. end;
  217. end;
  218. {****************************************************************************
  219. TM68KMOTASMLIST
  220. ****************************************************************************}
  221. var
  222. LastSec : tsection;
  223. const
  224. section2str : array[tsection] of string[6]=
  225. ('','CODE','DATA','BSS','');
  226. procedure tm68kmotasmlist.WriteTree(p:paasmoutput);
  227. var
  228. hp : pai;
  229. s : string;
  230. counter,
  231. i,j,lines : longint;
  232. quoted : boolean;
  233. begin
  234. if not assigned(p) then
  235. exit;
  236. hp:=pai(p^.first);
  237. while assigned(hp) do
  238. begin
  239. case hp^.typ of
  240. ait_comment : Begin
  241. AsmWrite(target_asm.comment);
  242. AsmWritePChar(pai_asm_comment(hp)^.str);
  243. AsmLn;
  244. End;
  245. ait_section : begin
  246. if pai_section(hp)^.sec<>sec_none then
  247. begin
  248. AsmLn;
  249. AsmWriteLn('SECTION _'+section2str[pai_section(hp)^.sec]+','+section2str[pai_section(hp)^.sec]);
  250. end;
  251. LastSec:=pai_section(hp)^.sec;
  252. end;
  253. {$ifdef DREGALLOC}
  254. ait_regalloc : AsmWriteLn(target_asm.comment+'Register '+att_reg2str[pairegalloc(hp)^.reg]+' allocated');
  255. ait_regdealloc : AsmWriteLn(target_asm.comment+'Register '+att_reg2str[pairegalloc(hp)^.reg]+' released');
  256. {$endif DREGALLOC}
  257. ait_align : AsmWriteLn(#9'CNOP 0,'+tostr(pai_align(hp)^.aligntype));
  258. ait_external : AsmWriteLn(#9'XREF'#9+StrPas(pai_external(hp)^.name));
  259. ait_real_extended : Message(assem_e_extended_not_supported);
  260. ait_comp : Message(assem_e_comp_not_supported);
  261. ait_datablock : begin
  262. { ------------------------------------------------------- }
  263. { ----------- ALIGNMENT FOR ANY NON-BYTE VALUE ---------- }
  264. { ------------- REQUIREMENT FOR 680x0 ------------------- }
  265. { ------------------------------------------------------- }
  266. if pai_datablock(hp)^.size <> 1 then
  267. begin
  268. if not(cs_littlesize in aktglobalswitches) then
  269. AsmWriteLn(#9'CNOP 0,4')
  270. else
  271. AsmWriteLn(#9'CNOP 0,2');
  272. end;
  273. if pai_datablock(hp)^.is_global then
  274. AsmWriteLn(#9'XDEF'#9+StrPas(pai_datablock(hp)^.name));
  275. AsmWriteLn(StrPas(pai_datablock(hp)^.name)+#9#9'DS.B '+tostr(pai_datablock(hp)^.size));
  276. end;
  277. ait_const_32bit : Begin
  278. AsmWriteLn(#9#9'DC.L'#9+tostr(pai_const(hp)^.value));
  279. end;
  280. ait_const_16bit : Begin
  281. AsmWriteLn(#9#9'DC.W'#9+tostr(pai_const(hp)^.value));
  282. end;
  283. ait_const_8bit : AsmWriteLn(#9#9'DC.B'#9+tostr(pai_const(hp)^.value));
  284. ait_const_symbol : Begin
  285. AsmWriteLn(#9#9+'DC.L '#9+StrPas(pchar(pai_const(hp)^.value)));
  286. end;
  287. ait_real_64bit : Begin
  288. AsmWriteLn(#9#9'DC.D'#9+double2str(pai_double(hp)^.value));
  289. end;
  290. ait_real_32bit : Begin
  291. AsmWriteLn(#9#9'DC.S'#9+double2str(pai_single(hp)^.value));
  292. end;
  293. { TO SUPPORT SOONER OR LATER!!!
  294. ait_comp : AsmWriteLn(#9#9'DC.D'#9+comp2str(pai_extended(hp)^.value));}
  295. ait_string : begin
  296. counter := 0;
  297. lines := pai_string(hp)^.len div line_length;
  298. { separate lines in different parts }
  299. if pai_string(hp)^.len > 0 then
  300. Begin
  301. for j := 0 to lines-1 do
  302. begin
  303. AsmWrite(#9#9'DC.B'#9);
  304. quoted:=false;
  305. for i:=counter to counter+line_length do
  306. begin
  307. { it is an ascii character. }
  308. if (ord(pai_string(hp)^.str[i])>31) and
  309. (ord(pai_string(hp)^.str[i])<128) and
  310. (pai_string(hp)^.str[i]<>'"') then
  311. begin
  312. if not(quoted) then
  313. begin
  314. if i>counter then
  315. AsmWrite(',');
  316. AsmWrite('"');
  317. end;
  318. AsmWrite(pai_string(hp)^.str[i]);
  319. quoted:=true;
  320. end { if > 31 and < 128 and ord('"') }
  321. else
  322. begin
  323. if quoted then
  324. AsmWrite('"');
  325. if i>counter then
  326. AsmWrite(',');
  327. quoted:=false;
  328. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  329. end;
  330. end; { end for i:=0 to... }
  331. if quoted then AsmWrite('"');
  332. AsmLn;
  333. counter := counter+line_length;
  334. end; { end for j:=0 ... }
  335. { do last line of lines }
  336. AsmWrite(#9#9'DC.B'#9);
  337. quoted:=false;
  338. for i:=counter to pai_string(hp)^.len-1 do
  339. begin
  340. { it is an ascii character. }
  341. if (ord(pai_string(hp)^.str[i])>31) and
  342. (ord(pai_string(hp)^.str[i])<128) and
  343. (pai_string(hp)^.str[i]<>'"') then
  344. begin
  345. if not(quoted) then
  346. begin
  347. if i>counter then
  348. AsmWrite(',');
  349. AsmWrite('"');
  350. end;
  351. AsmWrite(pai_string(hp)^.str[i]);
  352. quoted:=true;
  353. end { if > 31 and < 128 and " }
  354. else
  355. begin
  356. if quoted then
  357. AsmWrite('"');
  358. if i>counter then
  359. AsmWrite(',');
  360. quoted:=false;
  361. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  362. end;
  363. end; { end for i:=0 to... }
  364. if quoted then AsmWrite('"');
  365. end; { endif }
  366. AsmLn;
  367. end;
  368. ait_label : begin
  369. if assigned(hp^.next) and (pai(hp^.next)^.typ in
  370. [ait_const_32bit,ait_const_16bit,ait_const_symbol,ait_const_8bit,
  371. ait_real_64bit,ait_real_32bit,ait_string]) then
  372. begin
  373. if not(cs_littlesize in aktglobalswitches) then
  374. AsmWriteLn(#9'CNOP 0,4')
  375. else
  376. AsmWriteLn(#9'CNOP 0,2');
  377. end;
  378. AsmWrite(lab2str(pai_label(hp)^.l));
  379. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  380. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  381. ait_real_64bit,ait_string]) then
  382. AsmWriteLn(':');
  383. end;
  384. ait_direct : begin
  385. AsmWritePChar(pai_direct(hp)^.str);
  386. AsmLn;
  387. end;
  388. ait_labeled_instruction :
  389. Begin
  390. { labeled operand }
  391. if pai_labeled(hp)^._op1 = R_NO then
  392. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^._operator]+#9+lab2str(pai_labeled(hp)^.lab))
  393. else
  394. { labeled operand with register }
  395. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^._operator]+#9+
  396. reg2str(pai_labeled(hp)^._op1)+','+lab2str(pai_labeled(hp)^.lab))
  397. end;
  398. ait_symbol : begin
  399. { ------------------------------------------------------- }
  400. { ----------- ALIGNMENT FOR ANY NON-BYTE VALUE ---------- }
  401. { ------------- REQUIREMENT FOR 680x0 ------------------- }
  402. { ------------------------------------------------------- }
  403. if assigned(hp^.next) and (pai(hp^.next)^.typ in
  404. [ait_const_32bit,ait_const_16bit,ait_const_symbol,ait_const_8bit,
  405. ait_real_64bit,ait_real_32bit,ait_string]) then
  406. begin
  407. if not(cs_littlesize in aktglobalswitches) then
  408. AsmWriteLn(#9'CNOP 0,4')
  409. else
  410. AsmWriteLn(#9'CNOP 0,2');
  411. end;
  412. if pai_symbol(hp)^.is_global then
  413. AsmWriteLn(#9'XDEF '+StrPas(pai_symbol(hp)^.name));
  414. AsmWritePChar(pai_symbol(hp)^.name);
  415. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  416. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  417. ait_real_64bit,ait_string,ait_real_32bit]) then
  418. AsmWriteLn(':');
  419. end;
  420. ait_instruction : begin
  421. s:=#9+mot_op2str[pai68k(hp)^._operator]+mot_opsize2str[pai68k(hp)^.size];
  422. if pai68k(hp)^.op1t<>top_none then
  423. begin
  424. { call and jmp need an extra handling }
  425. { this code is only called if jmp isn't a labeled instruction }
  426. if pai68k(hp)^._operator in [A_JSR,A_JMP] then
  427. s:=s+#9+getopstr_jmp(pai68k(hp)^.op1t,pai68k(hp)^.op1)
  428. else
  429. begin
  430. if pai68k(hp)^.op1t = top_reglist then
  431. s:=s+#9+getopstr(pai68k(hp)^.op1t,@(pai68k(hp)^.reglist))
  432. else
  433. s:=s+#9+getopstr(pai68k(hp)^.op1t,pai68k(hp)^.op1);
  434. if pai68k(hp)^.op2t<>top_none then
  435. begin
  436. if pai68k(hp)^.op2t = top_reglist then
  437. s:=s+','+getopstr(pai68k(hp)^.op2t,@pai68k(hp)^.reglist)
  438. else
  439. s:=s+','+getopstr(pai68k(hp)^.op2t,pai68k(hp)^.op2);
  440. { three operands }
  441. if pai68k(hp)^.op3t<>top_none then
  442. begin
  443. if (pai68k(hp)^._operator = A_DIVSL) or
  444. (pai68k(hp)^._operator = A_DIVUL) or
  445. (pai68k(hp)^._operator = A_MULU) or
  446. (pai68k(hp)^._operator = A_MULS) or
  447. (pai68k(hp)^._operator = A_DIVS) or
  448. (pai68k(hp)^._operator = A_DIVU) then
  449. s:=s+':'+getopstr(pai68k(hp)^.op3t,pai68k(hp)^.op3)
  450. else
  451. s:=s+','+getopstr(pai68k(hp)^.op3t,pai68k(hp)^.op3);
  452. end;
  453. end;
  454. end;
  455. end;
  456. AsmWriteLn(s);
  457. end;
  458. {$ifdef GDB}
  459. ait_stabn,
  460. ait_stabs,
  461. ait_stab_function_name : ;
  462. {$endif GDB}
  463. ait_marker : ;
  464. else
  465. internalerror(10000);
  466. end;
  467. hp:=pai(hp^.next);
  468. end;
  469. end;
  470. procedure tm68kmotasmlist.WriteAsmList;
  471. begin
  472. {$ifdef EXTDEBUG}
  473. if assigned(current_module^.mainsource) then
  474. comment(v_info,'Start writing motorola-styled assembler output for '+current_module^.mainsource^);
  475. {$endif}
  476. countlabelref:=false;
  477. WriteTree(externals);
  478. { WriteTree(debuglist);}
  479. WriteTree(codesegment);
  480. WriteTree(datasegment);
  481. WriteTree(consts);
  482. WriteTree(rttilist);
  483. WriteTree(bsssegment);
  484. Writetree(importssection);
  485. Writetree(exportssection);
  486. Writetree(resourcesection);
  487. countlabelref:=true;
  488. AsmLn;
  489. AsmWriteLn(#9'END');
  490. AsmLn;
  491. {$ifdef EXTDEBUG}
  492. if assigned(current_module^.mainsource) then
  493. comment(v_info,'Done writing motorola-styled assembler output for '+current_module^.mainsource^);
  494. {$endif}
  495. end;
  496. end.
  497. {
  498. $Log$
  499. Revision 1.10 1998-10-06 17:16:38 pierre
  500. * some memory leaks fixed (thanks to Peter for heaptrc !)
  501. Revision 1.9 1998/10/01 20:19:10 jonas
  502. + ait_marker support
  503. Revision 1.8 1998/09/16 01:08:08 carl
  504. * alignment of byte bugfix
  505. Revision 1.7 1998/08/10 14:49:38 peter
  506. + localswitches, moduleswitches, globalswitches splitting
  507. Revision 1.6 1998/07/10 10:50:56 peter
  508. * m68k updates
  509. Revision 1.5 1998/06/05 17:46:06 peter
  510. * tp doesn't like comp() typecast
  511. Revision 1.4 1998/06/04 23:51:30 peter
  512. * m68k compiles
  513. + .def file creation moved to gendef.pas so it could also be used
  514. for win32
  515. }