agrvgas.pas 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit the GAS asm writers for Risc-V32/Risc-V64
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. {****************************************************************************}
  18. { Helper routines for Instruction Writer }
  19. {****************************************************************************}
  20. unit agrvgas;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. systems,aasmbase,
  25. aasmtai,aasmdata,
  26. aggas,
  27. assemble,
  28. cpubase,cgutils,
  29. globtype;
  30. type
  31. TRVInstrWriter=class(TCPUInstrWriter)
  32. procedure WriteInstruction(hp : tai);override;
  33. end;
  34. TRVGNUAssembler=class(TGNUassembler)
  35. constructor CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean); override;
  36. function MakeCmdLine: TCmdStr; override;
  37. end;
  38. implementation
  39. uses
  40. cutils,globals,verbose,
  41. cgbase,
  42. itcpugas,cpuinfo,
  43. aasmcpu;
  44. function getreferencestring(asminfo: pasminfo; var ref : treference) : string;
  45. var
  46. s : string;
  47. begin
  48. with ref do
  49. begin
  50. if ((offset < -2048) or (offset > 2047)) and
  51. (refaddr = addr_no) then
  52. internalerror(2006052501);
  53. case refaddr of
  54. addr_no:
  55. s := '';
  56. addr_pic_no_got:
  57. internalerror(2016060501);
  58. else
  59. begin
  60. s :='';
  61. if not(refaddr in [addr_no,addr_pic_no_got,addr_plt]) then
  62. s := s+'(';
  63. if assigned(symbol) then
  64. begin
  65. if asminfo^.dollarsign<>'$' then
  66. begin
  67. s:=s+ApplyAsmSymbolRestrictions(symbol.name);
  68. if assigned(relsymbol) then
  69. s:=s+'-'+ApplyAsmSymbolRestrictions(relsymbol.name)
  70. end
  71. else
  72. begin
  73. s:=s+symbol.name;
  74. if assigned(relsymbol) then
  75. s:=s+'-'+relsymbol.name;
  76. end;
  77. end;
  78. end;
  79. end;
  80. if offset<0 then
  81. s:=s+tostr(offset)
  82. else
  83. if (offset>0) then
  84. begin
  85. if assigned(symbol) then
  86. s:=s+'+'+tostr(offset)
  87. else
  88. s:=s+tostr(offset);
  89. end;
  90. if not(refaddr in [addr_no,addr_pic_no_got,addr_plt]) then
  91. begin
  92. s := s+')';
  93. end;
  94. if (index=NR_NO) then
  95. begin
  96. if offset=0 then
  97. begin
  98. if not (assigned(symbol)) then
  99. s:=s+'0';
  100. end;
  101. if (base<>NR_NO) then
  102. s:=s+'('+gas_regname(base)+')'
  103. else if not assigned(symbol) then
  104. s:=s+'(0)';
  105. end
  106. else if (index<>NR_NO) and (base<>NR_NO) then
  107. begin
  108. if (offset=0) then
  109. s:=s+gas_regname(base)+','+gas_regname(index)
  110. else
  111. internalerror(2006052502);
  112. end
  113. else
  114. Internalerror(2021030602);
  115. case refaddr of
  116. addr_lo12: s:='%lo'+s;
  117. addr_hi20: s:='%hi'+s;
  118. addr_pcrel_lo12: s:='%pcrel_lo'+s;
  119. addr_pcrel_hi20: s:='%pcrel_hi'+s;
  120. addr_got_pcrel_hi: s:='%got_pcrel_hi'+s;
  121. addr_plt: s:=s+'@plt';
  122. else
  123. ;
  124. end;
  125. end;
  126. getreferencestring:=s;
  127. end;
  128. function getopstr(asminfo: pasminfo; const o:toper) : string;
  129. var
  130. hs : string;
  131. begin
  132. case o.typ of
  133. top_reg:
  134. getopstr:=gas_regname(o.reg);
  135. top_const:
  136. getopstr:=tostr(longint(o.val));
  137. top_ref:
  138. if o.ref^.refaddr=addr_full then
  139. begin
  140. hs:=o.ref^.symbol.name;
  141. if asminfo^.dollarsign<>'$' then
  142. hs:=ApplyAsmSymbolRestrictions(hs);
  143. if o.ref^.offset>0 then
  144. hs:=hs+'+'+tostr(o.ref^.offset)
  145. else
  146. if o.ref^.offset<0 then
  147. hs:=hs+tostr(o.ref^.offset);
  148. getopstr:=hs;
  149. end
  150. else
  151. getopstr:=getreferencestring(asminfo,o.ref^);
  152. top_fenceflags:
  153. begin
  154. getopstr:='';
  155. if ffI in o.fenceflags then getopstr:=getopstr+'i';
  156. if ffO in o.fenceflags then getopstr:=getopstr+'o';
  157. if ffR in o.fenceflags then getopstr:=getopstr+'r';
  158. if ffW in o.fenceflags then getopstr:=getopstr+'w';
  159. end;
  160. top_roundingmode:
  161. getopstr:=roundingmode2str[o.roundingmode];
  162. else
  163. internalerror(2002070604);
  164. end;
  165. end;
  166. Procedure TRVInstrWriter.WriteInstruction(hp : tai);
  167. var op: TAsmOp;
  168. s: string;
  169. i: byte;
  170. sep: string[3];
  171. begin
  172. s:=#9+gas_op2str[taicpu(hp).opcode];
  173. if taicpu(hp).condition<>C_None then
  174. s:=s+cond2str[taicpu(hp).condition];
  175. if taicpu(hp).memoryordering<>[] then
  176. begin
  177. s:=s+'.';
  178. if moAq in taicpu(hp).memoryordering then s:=s+'aq';
  179. if moRl in taicpu(hp).memoryordering then s:=s+'rl';
  180. end;
  181. if taicpu(hp).ops<>0 then
  182. begin
  183. sep:=#9;
  184. for i:=0 to taicpu(hp).ops-1 do
  185. begin
  186. s:=s+sep+getopstr(owner.asminfo,taicpu(hp).oper[i]^);
  187. sep:=',';
  188. end;
  189. end;
  190. owner.writer.AsmWriteLn(s);
  191. end;
  192. {****************************************************************************}
  193. { GNU RiscV Assembler writer }
  194. {****************************************************************************}
  195. constructor TRVGNUAssembler.CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean);
  196. begin
  197. inherited;
  198. InstrWriter := TRVInstrWriter.create(self);
  199. end;
  200. function TRVGNUAssembler.MakeCmdLine: TCmdStr;
  201. const
  202. arch_str: array[boolean,tcputype] of string[10] = (
  203. {$ifdef RISCV32}
  204. ('','rv32imac','rv32ima','rv32im','rv32i','rv32e','rv32imc','rv32ec'),
  205. ('','rv32imafdc','rv32imafd','rv32imfd','rv32ifd','rv32efd','rv32imcfd','rv32ecfd')
  206. {$endif RISCV32}
  207. {$ifdef RISCV64}
  208. ('','rv64imac','rv64ima','rv64im','rv64i'),
  209. ('','rv64imafdc','rv64imafd','rv64imfd','rv64ifd')
  210. {$endif RISCV64}
  211. );
  212. begin
  213. result := inherited MakeCmdLine;
  214. Replace(result,'$ARCH',arch_str[current_settings.fputype=fpu_fd,current_settings.cputype]);
  215. {$ifdef RISCV32}
  216. case target_info.abi of
  217. abi_riscv_ilp32:
  218. Replace(result,'$ABI','ilp32');
  219. abi_riscv_ilp32f:
  220. Replace(result,'$ABI','ilp32f');
  221. else
  222. Replace(result,'$ABI','ilp32d');
  223. end;
  224. {$endif RISCV32}
  225. {$ifdef RISCV64}
  226. case target_info.abi of
  227. abi_riscv_lp64:
  228. Replace(result,'$ABI','lp64');
  229. abi_riscv_lp64f:
  230. Replace(result,'$ABI','lp64f');
  231. else
  232. Replace(result,'$ABI','lp64d');
  233. end;
  234. {$endif RISCV64}
  235. end;
  236. const
  237. as_riscv_gas_info : tasminfo =
  238. (
  239. id : as_gas;
  240. idtxt : 'AS';
  241. asmbin : 'as';
  242. asmcmd : '-o $OBJ $EXTRAOPT -march=$ARCH -mabi=$ABI $ASM';
  243. supported_targets : [system_riscv32_linux,system_riscv64_linux];
  244. flags : [af_needar,af_smartlink_sections,af_supports_dwarf];
  245. labelprefix : '.L';
  246. labelmaxlen : -1;
  247. comment : '# ';
  248. dollarsign: '$';
  249. );
  250. begin
  251. RegisterAssembler(as_riscv_gas_info,TRVGNUAssembler);
  252. end.