ag68kmot.pas 24 KB

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