ag68kmot.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  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 aktswitches) 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. if not(cs_littlesize in aktswitches) then
  279. AsmWriteLn(#9'CNOP 0,4')
  280. else
  281. AsmWriteLn(#9'CNOP 0,2');
  282. AsmWriteLn(#9#9'DC.L'#9+tostr(pai_const(hp)^.value));
  283. end;
  284. ait_const_16bit : Begin
  285. if not(cs_littlesize in aktswitches) then
  286. AsmWriteLn(#9'CNOP 0,4')
  287. else
  288. AsmWriteLn(#9'CNOP 0,2');
  289. AsmWriteLn(#9#9'DC.W'#9+tostr(pai_const(hp)^.value));
  290. end;
  291. ait_const_8bit : AsmWriteLn(#9#9'DC.B'#9+tostr(pai_const(hp)^.value));
  292. ait_const_symbol : Begin
  293. if not(cs_littlesize in aktswitches) then
  294. AsmWriteLn(#9'CNOP 0,4')
  295. else
  296. AsmWriteLn(#9'CNOP 0,2');
  297. AsmWriteLn(#9#9+'DC.L '#9+StrPas(pchar(pai_const(hp)^.value)));
  298. end;
  299. ait_real_64bit : Begin
  300. if not(cs_littlesize in aktswitches) then
  301. AsmWriteLn(#9'CNOP 0,4')
  302. else
  303. AsmWriteLn(#9'CNOP 0,2');
  304. AsmWriteLn(#9#9'DC.D'#9+double2str(pai_double(hp)^.value));
  305. end;
  306. ait_real_32bit : Begin
  307. if not(cs_littlesize in aktswitches) then
  308. AsmWriteLn(#9'CNOP 0,4')
  309. else
  310. AsmWriteLn(#9'CNOP 0,2');
  311. AsmWriteLn(#9#9'DC.S'#9+double2str(pai_single(hp)^.value));
  312. end;
  313. { TO SUPPORT SOONER OR LATER!!!
  314. ait_comp : AsmWriteLn(#9#9'DC.D'#9+comp2str(pai_extended(hp)^.value));}
  315. ait_string : begin
  316. counter := 0;
  317. lines := pai_string(hp)^.len div line_length;
  318. { separate lines in different parts }
  319. if pai_string(hp)^.len > 0 then
  320. Begin
  321. for j := 0 to lines-1 do
  322. begin
  323. AsmWrite(#9#9'DC.B'#9);
  324. quoted:=false;
  325. for i:=counter to counter+line_length do
  326. begin
  327. { it is an ascii character. }
  328. if (ord(pai_string(hp)^.str[i])>31) and
  329. (ord(pai_string(hp)^.str[i])<128) and
  330. (pai_string(hp)^.str[i]<>'"') then
  331. begin
  332. if not(quoted) then
  333. begin
  334. if i>counter then
  335. AsmWrite(',');
  336. AsmWrite('"');
  337. end;
  338. AsmWrite(pai_string(hp)^.str[i]);
  339. quoted:=true;
  340. end { if > 31 and < 128 and ord('"') }
  341. else
  342. begin
  343. if quoted then
  344. AsmWrite('"');
  345. if i>counter then
  346. AsmWrite(',');
  347. quoted:=false;
  348. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  349. end;
  350. end; { end for i:=0 to... }
  351. if quoted then AsmWrite('"');
  352. AsmLn;
  353. counter := counter+line_length;
  354. end; { end for j:=0 ... }
  355. { do last line of lines }
  356. AsmWrite(#9#9'DC.B'#9);
  357. quoted:=false;
  358. for i:=counter to pai_string(hp)^.len-1 do
  359. begin
  360. { it is an ascii character. }
  361. if (ord(pai_string(hp)^.str[i])>31) and
  362. (ord(pai_string(hp)^.str[i])<128) and
  363. (pai_string(hp)^.str[i]<>'"') then
  364. begin
  365. if not(quoted) then
  366. begin
  367. if i>counter then
  368. AsmWrite(',');
  369. AsmWrite('"');
  370. end;
  371. AsmWrite(pai_string(hp)^.str[i]);
  372. quoted:=true;
  373. end { if > 31 and < 128 and " }
  374. else
  375. begin
  376. if quoted then
  377. AsmWrite('"');
  378. if i>counter then
  379. AsmWrite(',');
  380. quoted:=false;
  381. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  382. end;
  383. end; { end for i:=0 to... }
  384. if quoted then AsmWrite('"');
  385. end; { endif }
  386. AsmLn;
  387. end;
  388. ait_label : begin
  389. AsmWrite(lab2str(pai_label(hp)^.l));
  390. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  391. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  392. ait_real_64bit,ait_string]) then
  393. AsmWriteLn(':');
  394. end;
  395. ait_direct : begin
  396. AsmWritePChar(pai_direct(hp)^.str);
  397. AsmLn;
  398. end;
  399. ait_labeled_instruction :
  400. Begin
  401. { labeled operand }
  402. if pai_labeled(hp)^._op1 = R_NO then
  403. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^._operator]+#9+lab2str(pai_labeled(hp)^.lab))
  404. else
  405. { labeled operand with register }
  406. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^._operator]+#9+
  407. reg2str(pai_labeled(hp)^._op1)+','+lab2str(pai_labeled(hp)^.lab))
  408. end;
  409. ait_symbol : begin
  410. { ------------------------------------------------------- }
  411. { ----------- ALIGNMENT FOR ANY NON-BYTE VALUE ---------- }
  412. { ------------- REQUIREMENT FOR 680x0 ------------------- }
  413. { ------------------------------------------------------- }
  414. if assigned(hp^.next) and (pai(hp^.next)^.typ in
  415. [ait_const_32bit,ait_const_16bit,ait_const_symbol,
  416. ait_real_64bit,ait_real_32bit,ait_string]) then
  417. begin
  418. if not(cs_littlesize in aktswitches) then
  419. AsmWriteLn(#9'CNOP 0,4')
  420. else
  421. AsmWriteLn(#9'CNOP 0,2');
  422. end;
  423. if pai_symbol(hp)^.is_global then
  424. AsmWriteLn(#9'XDEF '+StrPas(pai_symbol(hp)^.name));
  425. AsmWritePChar(pai_symbol(hp)^.name);
  426. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  427. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  428. ait_real_64bit,ait_string,ait_real_32bit]) then
  429. AsmWriteLn(':');
  430. end;
  431. ait_instruction : begin
  432. s:=#9+mot_op2str[pai68k(hp)^._operator]+mot_opsize2str[pai68k(hp)^.size];
  433. if pai68k(hp)^.op1t<>top_none then
  434. begin
  435. { call and jmp need an extra handling }
  436. { this code is only called if jmp isn't a labeled instruction }
  437. if pai68k(hp)^._operator in [A_JSR,A_JMP] then
  438. s:=s+#9+getopstr_jmp(pai68k(hp)^.op1t,pai68k(hp)^.op1)
  439. else
  440. begin
  441. if pai68k(hp)^.op1t = top_reglist then
  442. s:=s+#9+getopstr(pai68k(hp)^.op1t,@(pai68k(hp)^.reglist))
  443. else
  444. s:=s+#9+getopstr(pai68k(hp)^.op1t,pai68k(hp)^.op1);
  445. if pai68k(hp)^.op2t<>top_none then
  446. begin
  447. if pai68k(hp)^.op2t = top_reglist then
  448. s:=s+','+getopstr(pai68k(hp)^.op2t,@pai68k(hp)^.reglist)
  449. else
  450. s:=s+','+getopstr(pai68k(hp)^.op2t,pai68k(hp)^.op2);
  451. { three operands }
  452. if pai68k(hp)^.op3t<>top_none then
  453. begin
  454. if (pai68k(hp)^._operator = A_DIVSL) or
  455. (pai68k(hp)^._operator = A_DIVUL) or
  456. (pai68k(hp)^._operator = A_MULU) or
  457. (pai68k(hp)^._operator = A_MULS) or
  458. (pai68k(hp)^._operator = A_DIVS) or
  459. (pai68k(hp)^._operator = A_DIVU) then
  460. s:=s+':'+getopstr(pai68k(hp)^.op3t,pai68k(hp)^.op3)
  461. else
  462. s:=s+','+getopstr(pai68k(hp)^.op3t,pai68k(hp)^.op3);
  463. end;
  464. end;
  465. end;
  466. end;
  467. AsmWriteLn(s);
  468. end;
  469. {$ifdef GDB}
  470. ait_stabn,
  471. ait_stabs,
  472. ait_stab_function_name : ;
  473. {$endif GDB}
  474. else
  475. internalerror(10000);
  476. end;
  477. hp:=pai(hp^.next);
  478. end;
  479. end;
  480. procedure tm68kmotasmlist.WriteAsmList;
  481. begin
  482. {$ifdef EXTDEBUG}
  483. if assigned(current_module^.mainsource) then
  484. comment(v_info,'Start writing motorola-styled assembler output for '+current_module^.mainsource^);
  485. {$endif}
  486. WriteTree(externals);
  487. { WriteTree(debuglist);}
  488. WriteTree(codesegment);
  489. WriteTree(datasegment);
  490. WriteTree(consts);
  491. WriteTree(rttilist);
  492. WriteTree(bsssegment);
  493. Writetree(importssection);
  494. Writetree(exportssection);
  495. Writetree(resourcesection);
  496. AsmLn;
  497. AsmWriteLn(#9'END');
  498. AsmLn;
  499. {$ifdef EXTDEBUG}
  500. if assigned(current_module^.mainsource) then
  501. comment(v_info,'Done writing motorola-styled assembler output for '+current_module^.mainsource^);
  502. {$endif}
  503. end;
  504. end.
  505. {
  506. $Log$
  507. Revision 1.5 1998-06-05 17:46:06 peter
  508. * tp doesn't like comp() typecast
  509. Revision 1.4 1998/06/04 23:51:30 peter
  510. * m68k compiles
  511. + .def file creation moved to gendef.pas so it could also be used
  512. for win32
  513. }