ag68kmot.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  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:=d;{ this generates a warning but this is not important }
  54. {$ifndef TP}
  55. {$warning The following warning can be ignored}
  56. {$endif TP}
  57. dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
  58. comp2str:=double2str(dd^);
  59. end;
  60. function getreferencestring(const ref : treference) : string;
  61. var
  62. s : string;
  63. begin
  64. s:='';
  65. if ref.isintvalue then
  66. s:='#'+tostr(ref.offset)
  67. else
  68. with ref do
  69. begin
  70. if (index=R_NO) and (base=R_NO) and (direction=dir_none) then
  71. begin
  72. if assigned(symbol) then
  73. begin
  74. s:=s+symbol^;
  75. if offset<0 then
  76. s:=s+tostr(offset)
  77. else
  78. if (offset>0) then
  79. s:=s+'+'+tostr(offset);
  80. end
  81. else
  82. begin
  83. { direct memory addressing }
  84. s:=s+'('+tostr(offset)+').l';
  85. end;
  86. end
  87. else
  88. begin
  89. if assigned(symbol) then
  90. s:=s+symbol^;
  91. if offset<0 then
  92. s:=s+tostr(offset)
  93. else
  94. if (offset>0) then
  95. begin
  96. if (symbol=nil) then s:=tostr(offset)
  97. else s:=s+'+'+tostr(offset);
  98. end;
  99. if (index<>R_NO) and (base=R_NO) and (direction=dir_none) then
  100. begin
  101. if (scalefactor = 1) or (scalefactor = 0) then
  102. begin
  103. if offset = 0 then
  104. s:=s+'0(,'+mot_reg2str[index]+'.l)'
  105. else
  106. s:=s+'(,'+mot_reg2str[index]+'.l)';
  107. end
  108. else
  109. begin
  110. if offset = 0 then
  111. s:=s+'0(,'+mot_reg2str[index]+'.l*'+tostr(scalefactor)+')'
  112. else
  113. s:=s+'(,'+mot_reg2str[index]+'.l*'+tostr(scalefactor)+')';
  114. end
  115. end
  116. else
  117. if (index=R_NO) and (base<>R_NO) and (direction=dir_inc) then
  118. begin
  119. if (scalefactor = 1) or (scalefactor = 0) then
  120. s:=s+'('+mot_reg2str[base]+')+'
  121. else
  122. InternalError(10002);
  123. end
  124. else
  125. if (index=R_NO) and (base<>R_NO) and (direction=dir_dec) then
  126. begin
  127. if (scalefactor = 1) or (scalefactor = 0) then
  128. s:=s+'-('+mot_reg2str[base]+')'
  129. else
  130. InternalError(10003);
  131. end
  132. else
  133. if (index=R_NO) and (base<>R_NO) and (direction=dir_none) then
  134. begin
  135. s:=s+'('+mot_reg2str[base]+')';
  136. end
  137. else
  138. if (index<>R_NO) and (base<>R_NO) and (direction=dir_none) then
  139. begin
  140. if (scalefactor = 1) or (scalefactor = 0) then
  141. begin
  142. if offset = 0 then
  143. s:=s+'0('+mot_reg2str[base]+','+mot_reg2str[index]+'.l)'
  144. else
  145. s:=s+'('+mot_reg2str[base]+','+mot_reg2str[index]+'.l)';
  146. end
  147. else
  148. begin
  149. if offset = 0 then
  150. s:=s+'0('+mot_reg2str[base]+','+mot_reg2str[index]+'.l*'+tostr(scalefactor)+')'
  151. else
  152. s:=s+'('+mot_reg2str[base]+','+mot_reg2str[index]+'.l*'+tostr(scalefactor)+')';
  153. end
  154. end
  155. { if this is not a symbol, and is not in the above, then there is an error }
  156. else
  157. if NOT assigned(symbol) then
  158. InternalError(10004);
  159. end; { endif }
  160. end; { end with }
  161. getreferencestring:=s;
  162. end;
  163. function getopstr(t : byte;o : pointer) : string;
  164. var
  165. hs : string;
  166. i: tregister;
  167. begin
  168. case t of
  169. top_reg : getopstr:=mot_reg2str[tregister(o)];
  170. top_reglist: begin
  171. hs:='';
  172. for i:=R_NO to R_FPSR do
  173. begin
  174. if i in tregisterlist(o^) then
  175. hs:=hs+mot_reg2str[i]+'/';
  176. end;
  177. delete(hs,length(hs),1);
  178. getopstr := hs;
  179. end;
  180. top_ref : getopstr:=getreferencestring(preference(o)^);
  181. top_const : getopstr:='#'+tostr(longint(o));
  182. top_symbol : begin
  183. { compare with i386 version, where this is a constant. }
  184. hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
  185. move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
  186. { inc(byte(hs[0]));}
  187. { hs[1]:='#';}
  188. if pcsymbol(o)^.offset>0 then
  189. hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
  190. else if pcsymbol(o)^.offset<0 then
  191. hs:=hs+tostr(pcsymbol(o)^.offset);
  192. getopstr:=hs;
  193. end;
  194. else internalerror(10001);
  195. end;
  196. end;
  197. function getopstr_jmp(t : byte;o : pointer) : string;
  198. var
  199. hs : string;
  200. begin
  201. case t of
  202. top_reg : getopstr_jmp:=mot_reg2str[tregister(o)];
  203. top_ref : getopstr_jmp:=getreferencestring(preference(o)^);
  204. top_const : getopstr_jmp:=tostr(longint(o));
  205. top_symbol : begin
  206. hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
  207. move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
  208. if pcsymbol(o)^.offset>0 then
  209. hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
  210. else if pcsymbol(o)^.offset<0 then
  211. hs:=hs+tostr(pcsymbol(o)^.offset);
  212. getopstr_jmp:=hs;
  213. end;
  214. else internalerror(10001);
  215. end;
  216. end;
  217. {****************************************************************************
  218. TM68KMOTASMLIST
  219. ****************************************************************************}
  220. procedure tm68kmotasmlist.WriteTree(p:paasmoutput);
  221. var
  222. hp : pai;
  223. s : string;
  224. counter,
  225. i,j,lines : longint;
  226. quoted : boolean;
  227. begin
  228. hp:=pai(p^.first);
  229. while assigned(hp) do
  230. begin
  231. case hp^.typ of
  232. ait_comment :
  233. Begin
  234. AsmWrite(As_comment);
  235. AsmWritePChar(pai_asm_comment(hp)^.str);
  236. AsmLn;
  237. End;
  238. ait_align : AsmWriteLn(#9'CNOP 0,'+tostr(pai_align(hp)^.aligntype));
  239. ait_external : AsmWriteLn(#9'XREF'#9+StrPas(pai_external(hp)^.name));
  240. ait_real_extended : Message(assem_e_extended_not_supported);
  241. ait_comp : Message(assem_e_comp_not_supported);
  242. ait_datablock : begin
  243. { ------------------------------------------------------- }
  244. { ----------- ALIGNMENT FOR ANY NON-BYTE VALUE ---------- }
  245. { ------------- REQUIREMENT FOR 680x0 ------------------- }
  246. { ------------------------------------------------------- }
  247. if pai_datablock(hp)^.size <> 1 then
  248. begin
  249. if not(cs_littlesize in aktswitches) then
  250. AsmWriteLn(#9'CNOP 0,4')
  251. else
  252. AsmWriteLn(#9'CNOP 0,2');
  253. end;
  254. if pai_datablock(hp)^.is_global then
  255. AsmWriteLn(#9'XDEF'#9+StrPas(pai_datablock(hp)^.name));
  256. AsmWriteLn(StrPas(pai_datablock(hp)^.name)+#9#9'DS.B '+tostr(pai_datablock(hp)^.size));
  257. end;
  258. ait_const_32bit : Begin
  259. if not(cs_littlesize in aktswitches) then
  260. AsmWriteLn(#9'CNOP 0,4')
  261. else
  262. AsmWriteLn(#9'CNOP 0,2');
  263. AsmWriteLn(#9#9'DC.L'#9+tostr(pai_const(hp)^.value));
  264. end;
  265. ait_const_16bit : Begin
  266. if not(cs_littlesize in aktswitches) then
  267. AsmWriteLn(#9'CNOP 0,4')
  268. else
  269. AsmWriteLn(#9'CNOP 0,2');
  270. AsmWriteLn(#9#9'DC.W'#9+tostr(pai_const(hp)^.value));
  271. end;
  272. ait_const_8bit : AsmWriteLn(#9#9'DC.B'#9+tostr(pai_const(hp)^.value));
  273. ait_const_symbol : 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+StrPas(pchar(pai_const(hp)^.value)));
  279. end;
  280. ait_real_64bit : 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.D'#9+double2str(pai_double(hp)^.value));
  286. end;
  287. ait_real_32bit : Begin
  288. if not(cs_littlesize in aktswitches) then
  289. AsmWriteLn(#9'CNOP 0,4')
  290. else
  291. AsmWriteLn(#9'CNOP 0,2');
  292. AsmWriteLn(#9#9'DC.S'#9+double2str(pai_single(hp)^.value));
  293. end;
  294. { TO SUPPORT SOONER OR LATER!!!
  295. ait_comp : AsmWriteLn(#9#9'DC.D'#9+comp2str(pai_extended(hp)^.value));}
  296. ait_string : begin
  297. counter := 0;
  298. lines := pai_string(hp)^.len div line_length;
  299. { separate lines in different parts }
  300. if pai_string(hp)^.len > 0 then
  301. Begin
  302. for j := 0 to lines-1 do
  303. begin
  304. AsmWrite(#9#9'DC.B'#9);
  305. quoted:=false;
  306. for i:=counter to counter+line_length do
  307. begin
  308. { it is an ascii character. }
  309. if (ord(pai_string(hp)^.str[i])>31) and
  310. (ord(pai_string(hp)^.str[i])<128) and
  311. (pai_string(hp)^.str[i]<>'"') then
  312. begin
  313. if not(quoted) then
  314. begin
  315. if i>counter then
  316. AsmWrite(',');
  317. AsmWrite('"');
  318. end;
  319. AsmWrite(pai_string(hp)^.str[i]);
  320. quoted:=true;
  321. end { if > 31 and < 128 and ord('"') }
  322. else
  323. begin
  324. if quoted then
  325. AsmWrite('"');
  326. if i>counter then
  327. AsmWrite(',');
  328. quoted:=false;
  329. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  330. end;
  331. end; { end for i:=0 to... }
  332. if quoted then AsmWrite('"');
  333. AsmWrite(target_info.newline);
  334. counter := counter+line_length;
  335. end; { end for j:=0 ... }
  336. { do last line of lines }
  337. AsmWrite(#9#9'DC.B'#9);
  338. quoted:=false;
  339. for i:=counter to pai_string(hp)^.len-1 do
  340. begin
  341. { it is an ascii character. }
  342. if (ord(pai_string(hp)^.str[i])>31) and
  343. (ord(pai_string(hp)^.str[i])<128) and
  344. (pai_string(hp)^.str[i]<>'"') then
  345. begin
  346. if not(quoted) then
  347. begin
  348. if i>counter then
  349. AsmWrite(',');
  350. AsmWrite('"');
  351. end;
  352. AsmWrite(pai_string(hp)^.str[i]);
  353. quoted:=true;
  354. end { if > 31 and < 128 and " }
  355. else
  356. begin
  357. if quoted then
  358. AsmWrite('"');
  359. if i>counter then
  360. AsmWrite(',');
  361. quoted:=false;
  362. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  363. end;
  364. end; { end for i:=0 to... }
  365. if quoted then AsmWrite('"');
  366. end; { endif }
  367. AsmLn;
  368. end;
  369. ait_label : begin
  370. AsmWrite(lab2str(pai_label(hp)^.l));
  371. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  372. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  373. ait_real_64bit,ait_string]) then
  374. AsmWriteLn(':');
  375. end;
  376. ait_direct : begin
  377. AsmWritePChar(pai_direct(hp)^.str);
  378. AsmLn;
  379. end;
  380. ait_labeled_instruction :
  381. Begin
  382. { labeled operand }
  383. if pai_labeled(hp)^._op1 = R_NO then
  384. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^._operator]+#9+lab2str(pai_labeled(hp)^.lab))
  385. else
  386. { labeled operand with register }
  387. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^._operator]+#9+
  388. reg2str(pai_labeled(hp)^._op1)+','+lab2str(pai_labeled(hp)^.lab))
  389. end;
  390. ait_symbol : begin
  391. { ------------------------------------------------------- }
  392. { ----------- ALIGNMENT FOR ANY NON-BYTE VALUE ---------- }
  393. { ------------- REQUIREMENT FOR 680x0 ------------------- }
  394. { ------------------------------------------------------- }
  395. if assigned(hp^.next) and (pai(hp^.next)^.typ in
  396. [ait_const_32bit,ait_const_16bit,ait_const_symbol,
  397. ait_real_64bit,ait_real_32bit,ait_string]) then
  398. begin
  399. if not(cs_littlesize in aktswitches) then
  400. AsmWriteLn(#9'CNOP 0,4')
  401. else
  402. AsmWriteLn(#9'CNOP 0,2');
  403. end;
  404. if pai_symbol(hp)^.is_global then
  405. AsmWriteLn(#9'XDEF '+StrPas(pai_symbol(hp)^.name));
  406. AsmWritePChar(pai_symbol(hp)^.name);
  407. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  408. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  409. ait_real_64bit,ait_string,ait_real_32bit]) then
  410. AsmWriteLn(':');
  411. end;
  412. ait_instruction : begin
  413. s:=#9+mot_op2str[pai68k(hp)^._operator]+mot_opsize2str[pai68k(hp)^.size];
  414. if pai68k(hp)^.op1t<>top_none then
  415. begin
  416. { call and jmp need an extra handling }
  417. { this code is only called if jmp isn't a labeled instruction }
  418. if pai68k(hp)^._operator in [A_JSR,A_JMP] then
  419. s:=s+#9+getopstr_jmp(pai68k(hp)^.op1t,pai68k(hp)^.op1)
  420. else
  421. begin
  422. if pai68k(hp)^.op1t = top_reglist then
  423. s:=s+#9+getopstr(pai68k(hp)^.op1t,@(pai68k(hp)^.reglist))
  424. else
  425. s:=s+#9+getopstr(pai68k(hp)^.op1t,pai68k(hp)^.op1);
  426. if pai68k(hp)^.op2t<>top_none then
  427. begin
  428. if pai68k(hp)^.op2t = top_reglist then
  429. s:=s+','+getopstr(pai68k(hp)^.op2t,@pai68k(hp)^.reglist)
  430. else
  431. s:=s+','+getopstr(pai68k(hp)^.op2t,pai68k(hp)^.op2);
  432. { three operands }
  433. if pai68k(hp)^.op3t<>top_none then
  434. begin
  435. if (pai68k(hp)^._operator = A_DIVSL) or
  436. (pai68k(hp)^._operator = A_DIVUL) or
  437. (pai68k(hp)^._operator = A_MULU) or
  438. (pai68k(hp)^._operator = A_MULS) or
  439. (pai68k(hp)^._operator = A_DIVS) or
  440. (pai68k(hp)^._operator = A_DIVU) then
  441. s:=s+':'+getopstr(pai68k(hp)^.op3t,pai68k(hp)^.op3)
  442. else
  443. s:=s+','+getopstr(pai68k(hp)^.op3t,pai68k(hp)^.op3);
  444. end;
  445. end;
  446. end;
  447. end;
  448. AsmWriteLn(s);
  449. end;
  450. {$ifdef GDB}
  451. ait_stabn,
  452. ait_stabs,
  453. ait_stab_function_name : ;
  454. {$endif GDB}
  455. else
  456. internalerror(10000);
  457. end;
  458. { if ((hp^.typ<>ait_label) and (hp^.typ<>ait_symbol)) or (assigned(hp^.next) and not(pai(hp^.next)^.typ in
  459. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  460. ait_real_64bit,ait_string])) then
  461. AsmLn}
  462. hp:=pai(hp^.next);
  463. end;
  464. end;
  465. procedure tm68kmotasmlist.WriteAsmList;
  466. begin
  467. {$ifdef EXTDEBUG}
  468. if assigned(current_module^.mainsource) then
  469. comment(v_info,'Start writing motorola-styled assembler output for '+current_module^.mainsource^);
  470. {$endif}
  471. WriteTree(externals);
  472. AsmLn;
  473. AsmWriteLn(#9'SECTION _CODE,CODE');
  474. WriteTree(codesegment);
  475. AsmLn;
  476. AsmWriteLn(#9'SECTION _DATA,DATA');
  477. { write a signature to the file }
  478. AsmWriteLn(#9'CNOP 0,4');
  479. {$ifdef EXTDEBUG}
  480. AsmWriteLn(#9'DC.B'#9'"compiled by FPC '+version_string+'\0"');
  481. AsmWriteLn(#9'DC.B'#9'"target: '+target_info.target_name+'\0"');
  482. {$endif EXTDEBUG}
  483. WriteTree(datasegment);
  484. WriteTree(consts);
  485. AsmLn;
  486. AsmWriteLn(#9'SECTION _BSS,BSS');
  487. WriteTree(bsssegment);
  488. AsmLn;
  489. AsmWriteLn(#9'END');
  490. {$ifdef EXTDEBUG}
  491. if assigned(current_module^.mainsource) then
  492. comment(v_info,'Done writing motorola-styled assembler output for '+current_module^.mainsource^);
  493. {$endif}
  494. end;
  495. end.
  496. {
  497. $Log$
  498. Revision 1.3 1998-05-23 01:20:58 peter
  499. + aktasmmode, aktoptprocessor, aktoutputformat
  500. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  501. + $LIBNAME to set the library name where the unit will be put in
  502. * splitted cgi386 a bit (codeseg to large for bp7)
  503. * nasm, tasm works again. nasm moved to ag386nsm.pas
  504. Revision 1.2 1998/04/29 10:33:42 pierre
  505. + added some code for ansistring (not complete nor working yet)
  506. * corrected operator overloading
  507. * corrected nasm output
  508. + started inline procedures
  509. + added starstarn : use ** for exponentiation (^ gave problems)
  510. + started UseTokenInfo cond to get accurate positions
  511. Revision 1.1.1.1 1998/03/25 11:18:16 root
  512. * Restored version
  513. Revision 1.3 1998/03/22 12:45:37 florian
  514. * changes of Carl-Eric to m68k target commit:
  515. - wrong nodes because of the new string cg in intel, I had to create
  516. this under m68k also ... had to work it out to fix potential alignment
  517. problems --> this removes the crash of the m68k compiler.
  518. - added absolute addressing in m68k assembler (required for Amiga startup)
  519. - fixed alignment problems (because of byte return values, alignment
  520. would not be always valid) -- is this ok if i change the offset if odd in
  521. setfirsttemp ?? -- it seems ok...
  522. Revision 1.2 1998/03/10 04:23:33 carl
  523. - removed in because can cause range check errors under BP
  524. Revision 1.1 1998/03/10 01:26:10 peter
  525. + new uniform names
  526. }