ag68kmot.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  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_const_symbol_offset :
  288. Begin
  289. AsmWrite(#9#9+'DC.L '#9);
  290. AsmWritePChar(pai_const_symbol_offset(hp)^.name);
  291. if pai_const_symbol_offset(hp)^.offset>0 then
  292. AsmWrite('+'+tostr(pai_const_symbol_offset(hp)^.offset))
  293. else if pai_const_symbol_offset(hp)^.offset<0 then
  294. AsmWrite(tostr(pai_const_symbol_offset(hp)^.offset));
  295. AsmLn;
  296. end;
  297. ait_real_64bit : Begin
  298. AsmWriteLn(#9#9'DC.D'#9+double2str(pai_double(hp)^.value));
  299. end;
  300. ait_real_32bit : Begin
  301. AsmWriteLn(#9#9'DC.S'#9+double2str(pai_single(hp)^.value));
  302. end;
  303. { TO SUPPORT SOONER OR LATER!!!
  304. ait_comp : AsmWriteLn(#9#9'DC.D'#9+comp2str(pai_extended(hp)^.value));}
  305. ait_string : begin
  306. counter := 0;
  307. lines := pai_string(hp)^.len div line_length;
  308. { separate lines in different parts }
  309. if pai_string(hp)^.len > 0 then
  310. Begin
  311. for j := 0 to lines-1 do
  312. begin
  313. AsmWrite(#9#9'DC.B'#9);
  314. quoted:=false;
  315. for i:=counter to counter+line_length do
  316. begin
  317. { it is an ascii character. }
  318. if (ord(pai_string(hp)^.str[i])>31) and
  319. (ord(pai_string(hp)^.str[i])<128) and
  320. (pai_string(hp)^.str[i]<>'"') then
  321. begin
  322. if not(quoted) then
  323. begin
  324. if i>counter then
  325. AsmWrite(',');
  326. AsmWrite('"');
  327. end;
  328. AsmWrite(pai_string(hp)^.str[i]);
  329. quoted:=true;
  330. end { if > 31 and < 128 and ord('"') }
  331. else
  332. begin
  333. if quoted then
  334. AsmWrite('"');
  335. if i>counter then
  336. AsmWrite(',');
  337. quoted:=false;
  338. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  339. end;
  340. end; { end for i:=0 to... }
  341. if quoted then AsmWrite('"');
  342. AsmLn;
  343. counter := counter+line_length;
  344. end; { end for j:=0 ... }
  345. { do last line of lines }
  346. AsmWrite(#9#9'DC.B'#9);
  347. quoted:=false;
  348. for i:=counter to pai_string(hp)^.len-1 do
  349. begin
  350. { it is an ascii character. }
  351. if (ord(pai_string(hp)^.str[i])>31) and
  352. (ord(pai_string(hp)^.str[i])<128) and
  353. (pai_string(hp)^.str[i]<>'"') then
  354. begin
  355. if not(quoted) then
  356. begin
  357. if i>counter then
  358. AsmWrite(',');
  359. AsmWrite('"');
  360. end;
  361. AsmWrite(pai_string(hp)^.str[i]);
  362. quoted:=true;
  363. end { if > 31 and < 128 and " }
  364. else
  365. begin
  366. if quoted then
  367. AsmWrite('"');
  368. if i>counter then
  369. AsmWrite(',');
  370. quoted:=false;
  371. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  372. end;
  373. end; { end for i:=0 to... }
  374. if quoted then AsmWrite('"');
  375. end; { endif }
  376. AsmLn;
  377. end;
  378. ait_label : begin
  379. if assigned(hp^.next) and (pai(hp^.next)^.typ in
  380. [ait_const_32bit,ait_const_16bit,ait_const_8bit,
  381. ait_const_symbol,ait_const_symbol_offset,
  382. ait_real_64bit,ait_real_32bit,ait_string]) then
  383. begin
  384. if not(cs_littlesize in aktglobalswitches) then
  385. AsmWriteLn(#9'CNOP 0,4')
  386. else
  387. AsmWriteLn(#9'CNOP 0,2');
  388. end;
  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,
  416. ait_const_symbol,ait_const_symbol_offset,ait_const_8bit,
  417. ait_real_64bit,ait_real_32bit,ait_string]) then
  418. begin
  419. if not(cs_littlesize in aktglobalswitches) then
  420. AsmWriteLn(#9'CNOP 0,4')
  421. else
  422. AsmWriteLn(#9'CNOP 0,2');
  423. end;
  424. if pai_symbol(hp)^.is_global then
  425. AsmWriteLn(#9'XDEF '+StrPas(pai_symbol(hp)^.name));
  426. AsmWritePChar(pai_symbol(hp)^.name);
  427. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  428. [ait_const_32bit,ait_const_16bit,ait_const_8bit,
  429. ait_const_symbol,ait_const_symbol_offset,
  430. ait_real_64bit,ait_string,ait_real_32bit]) then
  431. AsmWriteLn(':');
  432. end;
  433. ait_instruction : begin
  434. s:=#9+mot_op2str[pai68k(hp)^._operator]+mot_opsize2str[pai68k(hp)^.size];
  435. if pai68k(hp)^.op1t<>top_none then
  436. begin
  437. { call and jmp need an extra handling }
  438. { this code is only called if jmp isn't a labeled instruction }
  439. if pai68k(hp)^._operator in [A_JSR,A_JMP] then
  440. s:=s+#9+getopstr_jmp(pai68k(hp)^.op1t,pai68k(hp)^.op1)
  441. else
  442. begin
  443. if pai68k(hp)^.op1t = top_reglist then
  444. s:=s+#9+getopstr(pai68k(hp)^.op1t,@(pai68k(hp)^.reglist))
  445. else
  446. s:=s+#9+getopstr(pai68k(hp)^.op1t,pai68k(hp)^.op1);
  447. if pai68k(hp)^.op2t<>top_none then
  448. begin
  449. if pai68k(hp)^.op2t = top_reglist then
  450. s:=s+','+getopstr(pai68k(hp)^.op2t,@pai68k(hp)^.reglist)
  451. else
  452. s:=s+','+getopstr(pai68k(hp)^.op2t,pai68k(hp)^.op2);
  453. { three operands }
  454. if pai68k(hp)^.op3t<>top_none then
  455. begin
  456. if (pai68k(hp)^._operator = A_DIVSL) or
  457. (pai68k(hp)^._operator = A_DIVUL) or
  458. (pai68k(hp)^._operator = A_MULU) or
  459. (pai68k(hp)^._operator = A_MULS) or
  460. (pai68k(hp)^._operator = A_DIVS) or
  461. (pai68k(hp)^._operator = A_DIVU) then
  462. s:=s+':'+getopstr(pai68k(hp)^.op3t,pai68k(hp)^.op3)
  463. else
  464. s:=s+','+getopstr(pai68k(hp)^.op3t,pai68k(hp)^.op3);
  465. end;
  466. end;
  467. end;
  468. end;
  469. AsmWriteLn(s);
  470. end;
  471. {$ifdef GDB}
  472. ait_stabn,
  473. ait_stabs,
  474. ait_stab_function_name : ;
  475. {$endif GDB}
  476. ait_marker : ;
  477. else
  478. internalerror(10000);
  479. end;
  480. hp:=pai(hp^.next);
  481. end;
  482. end;
  483. procedure tm68kmotasmlist.WriteAsmList;
  484. begin
  485. {$ifdef EXTDEBUG}
  486. if assigned(current_module^.mainsource) then
  487. comment(v_info,'Start writing motorola-styled assembler output for '+current_module^.mainsource^);
  488. {$endif}
  489. countlabelref:=false;
  490. WriteTree(externals);
  491. { WriteTree(debuglist);}
  492. WriteTree(codesegment);
  493. WriteTree(datasegment);
  494. WriteTree(consts);
  495. WriteTree(rttilist);
  496. WriteTree(bsssegment);
  497. Writetree(importssection);
  498. Writetree(exportssection);
  499. Writetree(resourcesection);
  500. countlabelref:=true;
  501. AsmLn;
  502. AsmWriteLn(#9'END');
  503. AsmLn;
  504. {$ifdef EXTDEBUG}
  505. if assigned(current_module^.mainsource) then
  506. comment(v_info,'Done writing motorola-styled assembler output for '+current_module^.mainsource^);
  507. {$endif}
  508. end;
  509. end.
  510. {
  511. $Log$
  512. Revision 1.11 1998-10-12 12:20:45 pierre
  513. + added tai_const_symbol_offset
  514. for r : pointer = @var.field;
  515. * better message for different arg names on implementation
  516. of function
  517. Revision 1.10 1998/10/06 17:16:38 pierre
  518. * some memory leaks fixed (thanks to Peter for heaptrc !)
  519. Revision 1.9 1998/10/01 20:19:10 jonas
  520. + ait_marker support
  521. Revision 1.8 1998/09/16 01:08:08 carl
  522. * alignment of byte bugfix
  523. Revision 1.7 1998/08/10 14:49:38 peter
  524. + localswitches, moduleswitches, globalswitches splitting
  525. Revision 1.6 1998/07/10 10:50:56 peter
  526. * m68k updates
  527. Revision 1.5 1998/06/05 17:46:06 peter
  528. * tp doesn't like comp() typecast
  529. Revision 1.4 1998/06/04 23:51:30 peter
  530. * m68k compiles
  531. + .def file creation moved to gendef.pas so it could also be used
  532. for win32
  533. }