agcpugas.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements an asmoutput class for m68k GAS syntax
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. { This unit implements an asmoutput class for i386 AT&T syntax
  19. }
  20. unit agcpugas;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. cclasses,cpubase,
  25. globals,
  26. aasmbase,aasmtai,aasmcpu,assemble,aggas;
  27. type
  28. TM68kAssembler=class(TGNUassembler)
  29. public
  30. procedure WriteInstruction(hp: tai);override;
  31. end;
  32. const
  33. gas_opsize2str : array[topsize] of string[2] =
  34. ('','.b','.w','.l','.s','.d','.x',''
  35. );
  36. implementation
  37. uses
  38. cutils,systems,
  39. verbose;
  40. function getreferencestring(var ref : treference) : string;
  41. var
  42. s,basestr,indexstr : string;
  43. begin
  44. s:='';
  45. with ref do
  46. begin
  47. inc(offset,offsetfixup);
  48. offsetfixup:=0;
  49. basestr:=gas_reg2str[base.enum];
  50. indexstr:=gas_reg2str[index.enum];
  51. if assigned(symbol) then
  52. s:=s+symbol.name;
  53. if offset<0 then s:=s+tostr(offset)
  54. else if (offset>0) then
  55. begin
  56. if (symbol=nil) then s:=tostr(offset)
  57. else s:=s+'+'+tostr(offset);
  58. end
  59. else if (index.enum=R_NO) and (base.enum=R_NO) and not assigned(symbol) then
  60. s:=s+'0';
  61. if (index.enum<>R_NO) and (base.enum=R_NO) and (direction=dir_none) then
  62. begin
  63. if (scalefactor = 1) or (scalefactor = 0) then
  64. s:=s+'(,'+indexstr+'.l)'
  65. else
  66. s:=s+'(,'+indexstr+'.l*'+tostr(scalefactor)+')'
  67. end
  68. else if (index.enum=R_NO) and (base.enum<>R_NO) and (direction=dir_inc) then
  69. begin
  70. if (scalefactor = 1) or (scalefactor = 0) then
  71. s:=s+'('+basestr+')+'
  72. else
  73. InternalError(10002);
  74. end
  75. else if (index.enum=R_NO) and (base.enum<>R_NO) and (direction=dir_dec) then
  76. begin
  77. if (scalefactor = 1) or (scalefactor = 0) then
  78. s:=s+'-('+basestr+')'
  79. else
  80. InternalError(10003);
  81. end
  82. else if (index.enum=R_NO) and (base.enum<>R_NO) and (direction=dir_none) then
  83. begin
  84. s:=s+'('+basestr+')'
  85. end
  86. else if (index.enum<>R_NO) and (base.enum<>R_NO) and (direction=dir_none) then
  87. begin
  88. if (scalefactor = 1) or (scalefactor = 0) then
  89. s:=s+'('+basestr+','+indexstr+'.l)'
  90. else
  91. s:=s+'('+basestr+','+indexstr+'.l*'+tostr(scalefactor)+')';
  92. end;
  93. end;
  94. getreferencestring:=s;
  95. end;
  96. function getopstr(const o:toper) : string;
  97. var
  98. hs : string;
  99. i:Tsuperregister;
  100. begin
  101. case o.typ of
  102. top_reg : getopstr:=gas_reg2str[o.reg.enum];
  103. top_ref : getopstr:=getreferencestring(o.ref^);
  104. top_reglist : begin
  105. hs:='';
  106. for i:=first_supreg to last_supreg do
  107. begin
  108. if i in o.registerlist then
  109. hs:=hs+supreg_name(i)+'/';
  110. end;
  111. delete(hs,length(hs),1);
  112. getopstr := hs;
  113. end;
  114. top_const : getopstr:='#'+tostr(longint(o.val));
  115. top_symbol :
  116. { compare with i386, where a symbol is considered }
  117. { a constant. }
  118. begin
  119. if assigned(o.sym) then
  120. hs:='#'+o.sym.name
  121. else
  122. hs:='#';
  123. if o.symofs>0 then
  124. hs:=hs+'+'+tostr(o.symofs)
  125. else
  126. if o.symofs<0 then
  127. hs:=hs+tostr(o.symofs)
  128. else
  129. if not(assigned(o.sym)) then
  130. hs:=hs+'0';
  131. getopstr:=hs;
  132. end;
  133. else internalerror(10001);
  134. end;
  135. end;
  136. function getopstr_jmp(const o:toper) : string;
  137. var
  138. hs : string;
  139. begin
  140. case o.typ of
  141. top_reg : getopstr_jmp:=gas_reg2str[o.reg.enum];
  142. top_ref : getopstr_jmp:=getreferencestring(o.ref^);
  143. top_const : getopstr_jmp:=tostr(o.val);
  144. top_symbol : begin
  145. if assigned(o.sym) then
  146. hs:=o.sym.name
  147. else
  148. hs:='';
  149. if o.symofs>0 then
  150. hs:=hs+'+'+tostr(o.symofs)
  151. else
  152. if o.symofs<0 then
  153. hs:=hs+tostr(o.symofs)
  154. else
  155. if not(assigned(o.sym)) then
  156. hs:=hs+'0';
  157. getopstr_jmp:=hs;
  158. end;
  159. else internalerror(10001);
  160. end;
  161. end;
  162. {****************************************************************************
  163. TM68kASMOUTPUT
  164. ****************************************************************************}
  165. (*
  166. ait_instruction : begin
  167. { old versions of GAS don't like PEA.L and LEA.L }
  168. if (paicpu(hp)^.opcode in [
  169. A_LEA,A_PEA,A_ABCD,A_BCHG,A_BCLR,A_BSET,A_BTST,
  170. A_EXG,A_NBCD,A_SBCD,A_SWAP,A_TAS,A_SCC,A_SCS,
  171. A_SEQ,A_SGE,A_SGT,A_SHI,A_SLE,A_SLS,A_SLT,A_SMI,
  172. A_SNE,A_SPL,A_ST,A_SVC,A_SVS,A_SF]) then
  173. s:=#9+mot_op2str[paicpu(hp)^.opcode]
  174. else
  175. s:=#9+mot_op2str[paicpu(hp)^.opcode]+mit_opsize2str[paicpu(hp)^.opsize];
  176. if paicpu(hp)^.ops>0 then
  177. begin
  178. { call and jmp need an extra handling }
  179. { this code is only callded if jmp isn't a labeled instruction }
  180. if paicpu(hp)^.opcode in [A_BSR,A_BRA,A_LEA,A_PEA,A_JSR,A_JMP] then
  181. s:=s+#9#9+getopstr_jmp(paicpu(hp)^.oper[0])
  182. else
  183. s:=s+#9+getopstr(paicpu(hp)^.oper[0]);
  184. if paicpu(hp)^.ops>1 then
  185. begin
  186. s:=s+','+getopstr(paicpu(hp)^.oper[1]);
  187. { three operands }
  188. if paicpu(hp)^.ops>2 then
  189. begin
  190. if (paicpu(hp)^.opcode = A_DIVSL) or
  191. (paicpu(hp)^.opcode = A_DIVUL) or
  192. (paicpu(hp)^.opcode = A_MULU) or
  193. (paicpu(hp)^.opcode = A_MULS) or
  194. (paicpu(hp)^.opcode = A_DIVS) or
  195. (paicpu(hp)^.opcode = A_DIVU) then
  196. s:=s+':'+getopstr(paicpu(hp)^.oper[2])
  197. else
  198. s:=s+','+getopstr(paicpu(hp)^.oper[2]);
  199. end;
  200. end;
  201. end;
  202. AsmWriteLn(s);
  203. end;
  204. ait_labeled_instruction : begin
  205. { labeled operand }
  206. if pai_labeled(hp)^.register = R_NO then
  207. begin
  208. if pai_labeled(hp)^.lab <> nil then
  209. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^.opcode]+#9+pai_labeled(hp)^.lab^.name)
  210. else
  211. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^.opcode]+#9+pai_labeled(hp)^.sym^.name);
  212. end
  213. else
  214. { labeled operand with register }
  215. begin
  216. if pai_labeled(hp)^.lab <> nil then
  217. begin
  218. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^.opcode]+#9+
  219. gas_reg2str[pai_labeled(hp)^.register]+','+pai_labeled(hp)^.lab^.name);
  220. end
  221. else
  222. { a symbol is the value }
  223. begin
  224. AsmWriteLn(#9+mot_op2str[pai_labeled(hp)^.opcode]+#9+
  225. gas_reg2str[pai_labeled(hp)^.register]+','+pai_labeled(hp)^.sym^.name);
  226. end;
  227. end;
  228. end;
  229. *)
  230. { returns the opcode string }
  231. function getopcodestring(hp : tai) : string;
  232. var
  233. op : tasmop;
  234. s : string;
  235. begin
  236. op:=taicpu(hp).opcode;
  237. { old versions of GAS don't like PEA.L and LEA.L }
  238. if (op in [
  239. A_LEA,A_PEA,A_ABCD,A_BCHG,A_BCLR,A_BSET,A_BTST,
  240. A_EXG,A_NBCD,A_SBCD,A_SWAP,A_TAS,A_SCC,A_SCS,
  241. A_SEQ,A_SGE,A_SGT,A_SHI,A_SLE,A_SLS,A_SLT,A_SMI,
  242. A_SNE,A_SPL,A_ST,A_SVC,A_SVS,A_SF]) then
  243. s:=gas_op2str[op]
  244. else
  245. if op = A_SXX then
  246. s:=gas_op2str[op]+cond2str[taicpu(hp).condition]
  247. else
  248. if op in [a_dbxx,a_bxx,a_fbxx] then
  249. s:=gas_op2str[op]+cond2str[taicpu(hp).condition]+gas_opsize2str[taicpu(hp).opsize]
  250. else
  251. s:=gas_op2str[op]+gas_opsize2str[taicpu(hp).opsize];
  252. getopcodestring:=s;
  253. end;
  254. procedure TM68kAssembler. WriteInstruction(hp: tai);
  255. var
  256. op : tasmop;
  257. s : string;
  258. sep : char;
  259. calljmp : boolean;
  260. i : integer;
  261. begin
  262. if hp.typ <> ait_instruction then exit;
  263. op:=taicpu(hp).opcode;
  264. calljmp:=is_calljmp(op);
  265. { call maybe not translated to call }
  266. s:=#9+getopcodestring(hp);
  267. { process operands }
  268. if taicpu(hp).ops<>0 then
  269. begin
  270. { call and jmp need an extra handling }
  271. { this code is only called if jmp isn't a labeled instruction }
  272. { quick hack to overcome a problem with manglednames=255 chars }
  273. if calljmp then
  274. begin
  275. AsmWrite(s+#9);
  276. s:=getopstr_jmp(taicpu(hp).oper[0]);
  277. end
  278. else
  279. begin
  280. for i:=0 to taicpu(hp).ops-1 do
  281. begin
  282. if i=0 then
  283. sep:=#9
  284. else
  285. if ((op = A_DIVSL) or
  286. (op = A_DIVUL) or
  287. (op = A_MULU) or
  288. (op = A_MULS) or
  289. (op = A_DIVS) or
  290. (op = A_DIVU)) and (i=1) then
  291. sep:=':'
  292. else
  293. sep:=',';
  294. s:=s+sep+getopstr(taicpu(hp).oper[i])
  295. end;
  296. end;
  297. end;
  298. AsmWriteLn(s);
  299. end;
  300. {*****************************************************************************
  301. Initialize
  302. *****************************************************************************}
  303. const
  304. as_m68k_as_info : tasminfo =
  305. (
  306. id : as_gas;
  307. idtxt : 'AS';
  308. asmbin : 'as';
  309. asmcmd : '-o $OBJ $ASM';
  310. supported_target : system_any;
  311. outputbinary: false;
  312. allowdirect : true;
  313. needar : true;
  314. labelprefix_only_inside_procedure : false;
  315. labelprefix : '.L';
  316. comment : '# ';
  317. secnames : ('',
  318. '.text','.data','.bss',
  319. '','','','','','',
  320. '.stab','.stabstr','COMMON')
  321. );
  322. initialization
  323. RegisterAssembler(as_m68k_as_info,TM68kAssembler);
  324. end.
  325. {
  326. $Log$
  327. Revision 1.8 2004-04-25 21:26:16 florian
  328. * some m68k stuff fixed
  329. Revision 1.7 2003/02/19 22:00:16 daniel
  330. * Code generator converted to new register notation
  331. - Horribily outdated todo.txt removed
  332. Revision 1.6 2003/02/15 22:19:40 carl
  333. * bugfix of emissions of jmp instructions
  334. Revision 1.5 2003/01/08 18:43:57 daniel
  335. * Tregister changed into a record
  336. Revision 1.4 2002/11/30 23:33:02 carl
  337. * merges from Pierre's fixes in m68k fixes branch
  338. Revision 1.3 2002/09/07 15:25:11 peter
  339. * old logs removed and tabs fixed
  340. Revision 1.2 2002/08/13 18:58:54 carl
  341. + m68k problems with cvs fixed?()!
  342. }