ag68kmot.pas 23 KB

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