ag68kmot.pas 24 KB

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