ag68kmot.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  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. ait_align : AsmWriteLn(#9'CNOP 0,'+tostr(pai_align(hp)^.aligntype));
  213. ait_external : AsmWriteLn(#9'XREF'#9+StrPas(pai_external(hp)^.name));
  214. ait_real_extended : Message(assem_e_extended_not_supported);
  215. ait_comp : Message(assem_e_comp_not_supported);
  216. ait_datablock : begin
  217. { ------------------------------------------------------- }
  218. { ----------- ALIGNMENT FOR ANY NON-BYTE VALUE ---------- }
  219. { ------------- REQUIREMENT FOR 680x0 ------------------- }
  220. { ------------------------------------------------------- }
  221. if pai_datablock(hp)^.size <> 1 then
  222. begin
  223. if not(cs_littlesize in aktswitches) then
  224. AsmWriteLn(#9'CNOP 0,4')
  225. else
  226. AsmWriteLn(#9'CNOP 0,2');
  227. end;
  228. if pai_datablock(hp)^.is_global then
  229. AsmWriteLn(#9'XDEF'#9+StrPas(pai_datablock(hp)^.name));
  230. AsmWriteLn(StrPas(pai_datablock(hp)^.name)+#9#9'DS.B '+tostr(pai_datablock(hp)^.size));
  231. end;
  232. ait_const_32bit : Begin
  233. if not(cs_littlesize in aktswitches) then
  234. AsmWriteLn(#9'CNOP 0,4')
  235. else
  236. AsmWriteLn(#9'CNOP 0,2');
  237. AsmWriteLn(#9#9'DC.L'#9+tostr(pai_const(hp)^.value));
  238. end;
  239. ait_const_16bit : Begin
  240. if not(cs_littlesize in aktswitches) then
  241. AsmWriteLn(#9'CNOP 0,4')
  242. else
  243. AsmWriteLn(#9'CNOP 0,2');
  244. AsmWriteLn(#9#9'DC.W'#9+tostr(pai_const(hp)^.value));
  245. end;
  246. ait_const_8bit : AsmWriteLn(#9#9'DC.B'#9+tostr(pai_const(hp)^.value));
  247. ait_const_symbol : Begin
  248. if not(cs_littlesize in aktswitches) then
  249. AsmWriteLn(#9'CNOP 0,4')
  250. else
  251. AsmWriteLn(#9'CNOP 0,2');
  252. AsmWriteLn(#9#9+'DC.L '#9+StrPas(pchar(pai_const(hp)^.value)));
  253. end;
  254. ait_real_64bit : Begin
  255. if not(cs_littlesize in aktswitches) then
  256. AsmWriteLn(#9'CNOP 0,4')
  257. else
  258. AsmWriteLn(#9'CNOP 0,2');
  259. AsmWriteLn(#9#9'DC.D'#9+double2str(pai_double(hp)^.value));
  260. end;
  261. ait_real_32bit : Begin
  262. if not(cs_littlesize in aktswitches) then
  263. AsmWriteLn(#9'CNOP 0,4')
  264. else
  265. AsmWriteLn(#9'CNOP 0,2');
  266. AsmWriteLn(#9#9'DC.S'#9+double2str(pai_single(hp)^.value));
  267. end;
  268. { TO SUPPORT SOONER OR LATER!!!
  269. ait_comp : AsmWriteLn(#9#9'DC.D'#9+comp2str(pai_extended(hp)^.value));}
  270. ait_string : begin
  271. counter := 0;
  272. lines := pai_string(hp)^.len div line_length;
  273. { separate lines in different parts }
  274. if pai_string(hp)^.len > 0 then
  275. Begin
  276. for j := 0 to lines-1 do
  277. begin
  278. AsmWrite(#9#9'DC.B'#9);
  279. quoted:=false;
  280. for i:=counter to counter+line_length do
  281. begin
  282. { it is an ascii character. }
  283. if (ord(pai_string(hp)^.str[i])>31) and
  284. (ord(pai_string(hp)^.str[i])<128) and
  285. (pai_string(hp)^.str[i]<>'"') then
  286. begin
  287. if not(quoted) then
  288. begin
  289. if i>counter then
  290. AsmWrite(',');
  291. AsmWrite('"');
  292. end;
  293. AsmWrite(pai_string(hp)^.str[i]);
  294. quoted:=true;
  295. end { if > 31 and < 128 and ord('"') }
  296. else
  297. begin
  298. if quoted then
  299. AsmWrite('"');
  300. if i>counter then
  301. AsmWrite(',');
  302. quoted:=false;
  303. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  304. end;
  305. end; { end for i:=0 to... }
  306. if quoted then AsmWrite('"');
  307. AsmWrite(target_info.newline);
  308. counter := counter+line_length;
  309. end; { end for j:=0 ... }
  310. { do last line of lines }
  311. AsmWrite(#9#9'DC.B'#9);
  312. quoted:=false;
  313. for i:=counter to pai_string(hp)^.len-1 do
  314. begin
  315. { it is an ascii character. }
  316. if (ord(pai_string(hp)^.str[i])>31) and
  317. (ord(pai_string(hp)^.str[i])<128) and
  318. (pai_string(hp)^.str[i]<>'"') then
  319. begin
  320. if not(quoted) then
  321. begin
  322. if i>counter then
  323. AsmWrite(',');
  324. AsmWrite('"');
  325. end;
  326. AsmWrite(pai_string(hp)^.str[i]);
  327. quoted:=true;
  328. end { if > 31 and < 128 and " }
  329. else
  330. begin
  331. if quoted then
  332. AsmWrite('"');
  333. if i>counter then
  334. AsmWrite(',');
  335. quoted:=false;
  336. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  337. end;
  338. end; { end for i:=0 to... }
  339. if quoted then AsmWrite('"');
  340. end; { endif }
  341. AsmLn;
  342. end;
  343. ait_label : begin
  344. AsmWrite(lab2str(pai_label(hp)^.l));
  345. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  346. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  347. ait_real_64bit,ait_string]) then
  348. AsmWriteLn(':');
  349. end;
  350. ait_direct : begin
  351. AsmWritePChar(pai_direct(hp)^.str);
  352. AsmLn;
  353. end;
  354. ait_labeled_instruction :
  355. Begin
  356. { labeled operand }
  357. if pai_labeled(hp)^._op1 = R_NO then
  358. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^._operator]+#9+lab2str(pai_labeled(hp)^.lab))
  359. else
  360. { labeled operand with register }
  361. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^._operator]+#9+
  362. reg2str(pai_labeled(hp)^._op1)+','+lab2str(pai_labeled(hp)^.lab))
  363. end;
  364. ait_symbol : begin
  365. { ------------------------------------------------------- }
  366. { ----------- ALIGNMENT FOR ANY NON-BYTE VALUE ---------- }
  367. { ------------- REQUIREMENT FOR 680x0 ------------------- }
  368. { ------------------------------------------------------- }
  369. if assigned(hp^.next) and (pai(hp^.next)^.typ in
  370. [ait_const_32bit,ait_const_16bit,ait_const_symbol,
  371. ait_real_64bit,ait_real_32bit,ait_string]) then
  372. begin
  373. if not(cs_littlesize in aktswitches) then
  374. AsmWriteLn(#9'CNOP 0,4')
  375. else
  376. AsmWriteLn(#9'CNOP 0,2');
  377. end;
  378. if pai_symbol(hp)^.is_global then
  379. AsmWriteLn(#9'XDEF '+StrPas(pai_symbol(hp)^.name));
  380. AsmWritePChar(pai_symbol(hp)^.name);
  381. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  382. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  383. ait_real_64bit,ait_string,ait_real_32bit]) then
  384. AsmWriteLn(':');
  385. end;
  386. ait_instruction : begin
  387. s:=#9+mot_op2str[pai68k(hp)^._operator]+mot_opsize2str[pai68k(hp)^.size];
  388. if pai68k(hp)^.op1t<>top_none then
  389. begin
  390. { call and jmp need an extra handling }
  391. { this code is only called if jmp isn't a labeled instruction }
  392. if pai68k(hp)^._operator in [A_JSR,A_JMP] then
  393. s:=s+#9+getopstr_jmp(pai68k(hp)^.op1t,pai68k(hp)^.op1)
  394. else
  395. begin
  396. if pai68k(hp)^.op1t = top_reglist then
  397. s:=s+#9+getopstr(pai68k(hp)^.op1t,@(pai68k(hp)^.reglist))
  398. else
  399. s:=s+#9+getopstr(pai68k(hp)^.op1t,pai68k(hp)^.op1);
  400. if pai68k(hp)^.op2t<>top_none then
  401. begin
  402. if pai68k(hp)^.op2t = top_reglist then
  403. s:=s+','+getopstr(pai68k(hp)^.op2t,@pai68k(hp)^.reglist)
  404. else
  405. s:=s+','+getopstr(pai68k(hp)^.op2t,pai68k(hp)^.op2);
  406. { three operands }
  407. if pai68k(hp)^.op3t<>top_none then
  408. begin
  409. if (pai68k(hp)^._operator = A_DIVSL) or
  410. (pai68k(hp)^._operator = A_DIVUL) or
  411. (pai68k(hp)^._operator = A_MULU) or
  412. (pai68k(hp)^._operator = A_MULS) or
  413. (pai68k(hp)^._operator = A_DIVS) or
  414. (pai68k(hp)^._operator = A_DIVU) then
  415. s:=s+':'+getopstr(pai68k(hp)^.op3t,pai68k(hp)^.op3)
  416. else
  417. s:=s+','+getopstr(pai68k(hp)^.op3t,pai68k(hp)^.op3);
  418. end;
  419. end;
  420. end;
  421. end;
  422. AsmWriteLn(s);
  423. end;
  424. {$ifdef GDB}
  425. ait_stabn,
  426. ait_stabs,
  427. ait_stab_function_name : ;
  428. {$endif GDB}
  429. else
  430. internalerror(10000);
  431. end;
  432. { if ((hp^.typ<>ait_label) and (hp^.typ<>ait_symbol)) or (assigned(hp^.next) and not(pai(hp^.next)^.typ in
  433. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  434. ait_real_64bit,ait_string])) then
  435. AsmLn}
  436. hp:=pai(hp^.next);
  437. end;
  438. end;
  439. procedure tm68kmotasmlist.WriteAsmList;
  440. begin
  441. {$ifdef EXTDEBUG}
  442. if assigned(current_module^.mainsource) then
  443. comment(v_info,'Start writing motorola-styled assembler output for '+current_module^.mainsource^);
  444. {$endif}
  445. WriteTree(externals);
  446. AsmLn;
  447. AsmWriteLn(#9'SECTION _CODE,CODE');
  448. WriteTree(codesegment);
  449. AsmLn;
  450. AsmWriteLn(#9'SECTION _DATA,DATA');
  451. { write a signature to the file }
  452. AsmWriteLn(#9'CNOP 0,4');
  453. {$ifdef EXTDEBUG}
  454. AsmWriteLn(#9'DC.B'#9'"compiled by FPC '+version_string+'\0"');
  455. AsmWriteLn(#9'DC.B'#9'"target: '+target_info.target_name+'\0"');
  456. {$endif EXTDEBUG}
  457. WriteTree(datasegment);
  458. WriteTree(consts);
  459. AsmLn;
  460. AsmWriteLn(#9'SECTION _BSS,BSS');
  461. WriteTree(bsssegment);
  462. AsmLn;
  463. AsmWriteLn(#9'END');
  464. {$ifdef EXTDEBUG}
  465. if assigned(current_module^.mainsource) then
  466. comment(v_info,'Done writing motorola-styled assembler output for '+current_module^.mainsource^);
  467. {$endif}
  468. end;
  469. end.
  470. {
  471. $Log$
  472. Revision 1.1 1998-03-25 11:18:16 root
  473. Initial revision
  474. Revision 1.3 1998/03/22 12:45:37 florian
  475. * changes of Carl-Eric to m68k target commit:
  476. - wrong nodes because of the new string cg in intel, I had to create
  477. this under m68k also ... had to work it out to fix potential alignment
  478. problems --> this removes the crash of the m68k compiler.
  479. - added absolute addressing in m68k assembler (required for Amiga startup)
  480. - fixed alignment problems (because of byte return values, alignment
  481. would not be always valid) -- is this ok if i change the offset if odd in
  482. setfirsttemp ?? -- it seems ok...
  483. Revision 1.2 1998/03/10 04:23:33 carl
  484. - removed in because can cause range check errors under BP
  485. Revision 1.1 1998/03/10 01:26:10 peter
  486. + new uniform names
  487. }