ag68kmot.pas 22 KB

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