agcpugas.pas 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. {
  2. Copyright (C) 2022 Loongson Technology Corporation Limited.
  3. This unit the GAS asm writers for LoongArch64
  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 agcpugas;
  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. TLoongArch64InstrWriter=class(TCPUInstrWriter)
  32. procedure WriteInstruction(hp : tai);override;
  33. end;
  34. TLoongArch64GNUAssembler=class(TGNUassembler)
  35. constructor CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean); override;
  36. end;
  37. var
  38. curop: TAsmOp;
  39. implementation
  40. uses
  41. cutils,globals,verbose,
  42. cgbase,rgbase,
  43. itcpugas,cpuinfo,
  44. aasmcpu;
  45. function getreferencestring(asminfo: pasminfo; var ref : treference) : string;
  46. var
  47. s : string;
  48. begin
  49. { For LoongArch, we support only 4 cases
  50. 1. Symbol, symbol + addend (cannot used by got).
  51. 2. Reg + offset.
  52. 3. Reg + reg.
  53. 4. Reg
  54. }
  55. with ref do
  56. begin
  57. if assigned(relsymbol) then
  58. internalerror(2022081001);
  59. case refaddr of
  60. addr_b16, addr_b21, addr_b26, addr_pcrel,
  61. addr_plt, addr_abs_hi20, addr_abs_lo12,
  62. addr_abs64_lo20, addr_abs64_hi12,
  63. addr_pc_hi20, addr_got_pc_hi20,
  64. addr_pc_lo12, addr_got_pc_lo12,
  65. addr_got, addr_abs:
  66. begin
  67. if (base<>NR_NO) or (index<>NR_NO) then
  68. internalerror(2022081002)
  69. else if (refaddr in [addr_got_pc_hi20,addr_got_pc_lo12,addr_got]) and (offset<>0) then
  70. internalerror(2022081003)
  71. else if not assigned(symbol) then
  72. internalerror(2022081004);
  73. s:=ApplyAsmSymbolRestrictions(symbol.name);
  74. if offset<0 then
  75. s:=s+tostr(offset)
  76. else if offset>0 then
  77. s:=s+'+'+tostr(offset);
  78. case refaddr of
  79. addr_b16: s:='%b16('+s+')';
  80. addr_b21: s:='%b21('+s+')';
  81. addr_b26: s:='%b26('+s+')';
  82. addr_plt: s:='%plt('+s+')';
  83. addr_abs_hi20: s:='%abs_hi20('+s+')';
  84. addr_abs_lo12: s:='%abs_lo12('+s+')';
  85. addr_abs64_lo20: s:='%abs64_lo20('+s+')';
  86. addr_abs64_hi12: s:='%abs64_hi12('+s+')';
  87. addr_pc_hi20: s:='%pc_hi20('+s+')';
  88. addr_got_pc_hi20: s:='%got_pc_hi20('+s+')';
  89. addr_got_pc_lo12: s:='%got_pc_lo12('+s+')';
  90. addr_pc_lo12: s:='%pc_lo12('+s+')';
  91. else
  92. ;
  93. end;
  94. end;
  95. addr_reg_reg:
  96. begin
  97. if assigned(symbol) or (offset<>0) then
  98. internalerror(2022081005)
  99. else if (base=NR_NO) or (index=NR_NO) then
  100. internalerror(2022081006);
  101. s:=gas_regname(base)+','+gas_regname(index);
  102. end;
  103. addr_reg_12i, addr_reg_14i:
  104. begin
  105. if assigned(symbol) or (index<>NR_NO) then
  106. internalerror(2022081007)
  107. else if (refaddr=addr_reg_12i) and (not is_simm12(offset)) then
  108. internalerror(2022081008)
  109. else if (refaddr=addr_reg_14i) and (not is_simm16_and_quadruple(offset)) then
  110. internalerror(2022081009);
  111. s:=gas_regname(base)+','+tostr(offset);
  112. end;
  113. addr_reg:
  114. begin
  115. if assigned(symbol) or (index<>NR_NO) or (offset<>0) then
  116. internalerror(2022081010)
  117. else if (base=NR_NO) then
  118. internalerror(2022081011);
  119. s:=gas_regname(base);
  120. end;
  121. else
  122. internalerror(2022081012);
  123. end;
  124. end; { with ref do }
  125. getreferencestring:=s;
  126. end;
  127. function getopstr(asminfo: pasminfo; const o:toper;use_std_regname : boolean) : string;
  128. var
  129. hs : string;
  130. begin
  131. case o.typ of
  132. top_reg:
  133. if use_std_regname then
  134. getopstr:=std_regname(o.reg)
  135. else
  136. getopstr:=gas_regname(o.reg);
  137. top_const:
  138. getopstr:=tostr(o.val);
  139. top_ref:
  140. getopstr:=getreferencestring(asminfo,o.ref^);
  141. else
  142. internalerror(2022111901);
  143. end;
  144. end;
  145. Procedure TLoongArch64InstrWriter.WriteInstruction(hp : tai);
  146. var op: TAsmOp;
  147. s: string;
  148. i : byte;
  149. use_std_regname_index : byte;
  150. sep: string[3];
  151. begin
  152. s:=#9+gas_op2str[taicpu(hp).opcode];
  153. if taicpu(hp).condition<>C_None then
  154. s:=s+cond2str[taicpu(hp).condition];
  155. curop:=taicpu(hp).opcode;
  156. if curop=A_MOVFCSR2GR then
  157. use_std_regname_index:=1
  158. else if curop=A_MOVGR2FCSR then
  159. use_std_regname_index:=0
  160. else
  161. use_std_regname_index:=255;
  162. if taicpu(hp).ops<>0 then
  163. begin
  164. sep:=#9;
  165. for i:=0 to taicpu(hp).ops-1 do
  166. begin
  167. s:=s+sep+getopstr(owner.asminfo,taicpu(hp).oper[i]^,use_std_regname_index=i);
  168. sep:=',';
  169. end;
  170. end;
  171. owner.writer.AsmWriteLn(s);
  172. end;
  173. {****************************************************************************}
  174. { GNU LoongArch Assembler writer }
  175. {****************************************************************************}
  176. constructor TLoongArch64GNUAssembler.CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean);
  177. begin
  178. inherited;
  179. InstrWriter := TLoongArch64InstrWriter.create(self);
  180. end;
  181. const
  182. as_loongarch64_gas_info : tasminfo =
  183. (
  184. id : as_gas;
  185. idtxt : 'AS';
  186. asmbin : 'as';
  187. asmcmd : '-o $OBJ $EXTRAOPT -mabi=lp64d $ASM';
  188. supported_targets : [system_loongarch64_linux];
  189. flags : [af_needar,af_smartlink_sections];
  190. labelprefix : '.L';
  191. labelmaxlen : -1;
  192. comment : '# ';
  193. dollarsign: '$';
  194. );
  195. begin
  196. RegisterAssembler(as_loongarch64_gas_info,TLoongArch64GNUAssembler);
  197. end.