agarmgas.pas 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. {
  2. $Id$
  3. Copyright (c) 2003 by Florian Klaempfl
  4. This unit implements an asm for the ARM
  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 the GNU Assembler writer for the ARM
  19. }
  20. unit agarmgas;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. aasmtai,
  25. aggas,
  26. cpubase;
  27. type
  28. PARMGNUAssembler=^TARMGNUAssembler;
  29. TARMGNUAssembler=class(TGNUassembler)
  30. procedure WriteInstruction(hp : tai);override;
  31. end;
  32. var
  33. gas_reg2str : reg2strtable;
  34. function gas_regnum_search(const s:string):Tnewregister;
  35. function gas_regname(const r:Tnewregister):string;
  36. implementation
  37. uses
  38. cutils,globals,verbose,
  39. systems,
  40. assemble,
  41. aasmcpu;
  42. const
  43. as_arm_gas_info : tasminfo =
  44. (
  45. id : as_gas;
  46. idtxt : 'AS';
  47. asmbin : 'as';
  48. asmcmd : '-o $OBJ $ASM';
  49. supported_target : system_any;
  50. outputbinary: false;
  51. allowdirect : true;
  52. needar : true;
  53. labelprefix_only_inside_procedure : false;
  54. labelprefix : '.L';
  55. comment : '# ';
  56. secnames : ('',
  57. '.text','.data','.text',
  58. '','','','','','',
  59. '.stab','.stabstr','COMMON')
  60. );
  61. function getreferencestring(var ref : treference) : string;
  62. var
  63. s : string;
  64. begin
  65. with ref do
  66. begin
  67. inc(offset,offsetfixup);
  68. if not assigned(symbol) then
  69. s := '['
  70. else
  71. s:='['+symbol.name;
  72. if offset<0 then
  73. s:=s+tostr(offset)
  74. else
  75. if (offset>0) then
  76. begin
  77. if assigned(symbol) then
  78. s:=s+'+'+tostr(offset)
  79. else
  80. s:=s+tostr(offset);
  81. end;
  82. if (index.enum < firstreg) or (index.enum > lastreg) then
  83. internalerror(20030312);
  84. if (base.enum < firstreg) or (base.enum > lastreg) then
  85. internalerror(200303123);
  86. if (index.enum=R_NO) and (base.enum<>R_NO) then
  87. begin
  88. if offset=0 then
  89. begin
  90. if assigned(symbol) then
  91. s:=s+'+0'
  92. else
  93. s:=s+'0';
  94. end;
  95. s:=s+'['+std_reg2str[base.enum]+']'
  96. end
  97. else if (index.enum<>R_NO) and (base.enum<>R_NO) and (offset=0) then
  98. s:=s+std_reg2str[base.enum]+','+std_reg2str[index.enum]
  99. else if ((index.enum<>R_NO) or (base.enum<>R_NO)) then
  100. internalerror(19992);
  101. end;
  102. getreferencestring:=s;
  103. end;
  104. function getopstr_jmp(const o:toper) : string;
  105. var
  106. hs : string;
  107. begin
  108. case o.typ of
  109. top_reg :
  110. begin
  111. if (o.reg.enum < R_R0) or (o.reg.enum > lastreg) then
  112. internalerror(200303121);
  113. getopstr_jmp:=std_reg2str[o.reg.enum];
  114. end;
  115. top_shifterop:
  116. begin
  117. end;
  118. { no top_ref jumping for powerpc }
  119. top_const :
  120. getopstr_jmp:=tostr(o.val);
  121. top_symbol :
  122. begin
  123. hs:=o.sym.name;
  124. if o.symofs>0 then
  125. hs:=hs+'+'+tostr(o.symofs)
  126. else
  127. if o.symofs<0 then
  128. hs:=hs+tostr(o.symofs);
  129. getopstr_jmp:=hs;
  130. end;
  131. top_none:
  132. getopstr_jmp:='';
  133. else
  134. {$ifndef testing}
  135. internalerror(2002070603);
  136. {$else testing}
  137. begin
  138. writeln('internalerror 10001');
  139. halt(1);
  140. end;
  141. {$endif testing}
  142. end;
  143. end;
  144. const
  145. shifterop2str: array[tshiftertype] of string[3] = ('','asr','lsl','lsr','ror','rrx');
  146. function getopstr(const o:toper) : string;
  147. var
  148. hs : string;
  149. begin
  150. case o.typ of
  151. top_reg:
  152. begin
  153. if (o.reg.enum < R_R0) or (o.reg.enum > lastreg) then
  154. internalerror(200303125);
  155. getopstr:=std_reg2str[o.reg.enum];
  156. end;
  157. top_shifterop:
  158. begin
  159. end;
  160. top_const:
  161. getopstr:=tostr(longint(o.val));
  162. top_ref:
  163. getopstr:=getreferencestring(o.ref^);
  164. top_symbol:
  165. begin
  166. hs:=o.sym.name;
  167. if o.symofs>0 then
  168. hs:=hs+'+'+tostr(o.symofs)
  169. else
  170. if o.symofs<0 then
  171. hs:=hs+tostr(o.symofs);
  172. getopstr:=hs;
  173. end;
  174. else
  175. {$ifndef testing}
  176. internalerror(2002070604);
  177. {$else testing}
  178. begin
  179. writeln('internalerror 10001');
  180. halt(1);
  181. end;
  182. {$endif testing}
  183. end;
  184. end;
  185. Procedure TARMGNUAssembler.WriteInstruction(hp : tai);
  186. var op: TAsmOp;
  187. s: string;
  188. i: byte;
  189. sep: string[3];
  190. begin
  191. op:=taicpu(hp).opcode;
  192. if is_calljmp(op) then
  193. begin
  194. {
  195. { direct BO/BI in op[0] and op[1] not supported, put them in condition! }
  196. case op of
  197. A_B,A_BA,A_BL,A_BLA:
  198. s:=#9+op2str[op]+#9;
  199. A_BCTR,A_BCTRL,A_BLR,A_BLRL:
  200. s:=#9+op2str[op]
  201. else
  202. s:=cond2str(op,taicpu(hp).condition)+',';
  203. end;
  204. if (taicpu(hp).oper[0].typ <> top_none) then
  205. s:=s+getopstr_jmp(taicpu(hp).oper[0]);
  206. }
  207. end
  208. else
  209. { process operands }
  210. begin
  211. s:=#9+std_op2str[op];
  212. if taicpu(hp).ops<>0 then
  213. begin
  214. {
  215. if not is_calljmp(op) then
  216. sep:=','
  217. else
  218. }
  219. sep:=#9;
  220. for i:=0 to taicpu(hp).ops-1 do
  221. begin
  222. // debug code
  223. // writeln(s);
  224. // writeln(taicpu(hp).fileinfo.line);
  225. s:=s+sep+getopstr(taicpu(hp).oper[i]);
  226. sep:=',';
  227. end;
  228. end;
  229. end;
  230. AsmWriteLn(s);
  231. end;
  232. function gas_regnum_search(const s:string):Tnewregister;
  233. begin
  234. end;
  235. function gas_regname(const r:Tnewregister):string;
  236. begin
  237. end;
  238. begin
  239. RegisterAssembler(as_arm_gas_info,TARMGNUAssembler);
  240. gas_reg2str:=std_reg2str;
  241. end.
  242. {
  243. $Log$
  244. Revision 1.3 2003-08-24 12:27:26 florian
  245. * continued to work on the arm port
  246. Revision 1.2 2003/08/20 15:50:12 florian
  247. * more arm stuff
  248. Revision 1.1 2003/08/16 13:23:01 florian
  249. * several arm related stuff fixed
  250. }