cpugas.pas 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. {
  2. Copyright (c) 1999-2009 by Florian Klaempfl and David Zhang
  3. This unit implements an asmoutput class for MIPS assembly syntax
  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. unit cpugas;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cpubase,
  22. aasmtai, aasmcpu, assemble, aggas;
  23. type
  24. TMIPSGNUAssembler = class(TGNUassembler)
  25. constructor create(smart: boolean); override;
  26. end;
  27. TMIPSInstrWriter = class(TCPUInstrWriter)
  28. procedure WriteInstruction(hp : tai);override;
  29. end;
  30. implementation
  31. uses
  32. cutils, systems,
  33. verbose, itcpugas, cgbase, cgutils;
  34. {****************************************************************************}
  35. { GNU MIPS Assembler writer }
  36. {****************************************************************************}
  37. constructor TMIPSGNUAssembler.create(smart: boolean);
  38. begin
  39. inherited create(smart);
  40. InstrWriter := TMIPSInstrWriter.create(self);
  41. end;
  42. {****************************************************************************}
  43. { Helper routines for Instruction Writer }
  44. {****************************************************************************}
  45. function GetReferenceString(var ref: TReference): string;
  46. begin
  47. GetReferenceString := '';
  48. with ref do
  49. begin
  50. if (base = NR_NO) and (index = NR_NO) then
  51. begin
  52. if assigned(symbol) then
  53. GetReferenceString := symbol.Name;
  54. if offset > 0 then
  55. GetReferenceString := GetReferenceString + '+' + ToStr(offset)
  56. else if offset < 0 then
  57. GetReferenceString := GetReferenceString + ToStr(offset);
  58. case refaddr of
  59. addr_high:
  60. GetReferenceString := '%hi(' + GetReferenceString + ')';
  61. addr_low:
  62. GetReferenceString := '%lo(' + GetReferenceString + ')';
  63. end;
  64. end
  65. else
  66. begin
  67. {$ifdef extdebug}
  68. if assigned(symbol) and
  69. not(refaddr in [addr_pic,addr_low]) then
  70. internalerror(2003052601);
  71. {$endif extdebug}
  72. if base <> NR_NO then
  73. GetReferenceString := GetReferenceString + '(' + gas_regname(base) + ')';
  74. if index = NR_NO then
  75. begin
  76. if offset <> 0 then
  77. GetReferenceString := ToStr(offset) + GetReferenceString;
  78. if assigned(symbol) then
  79. begin
  80. if refaddr = addr_low then
  81. GetReferenceString := '%lo(' + symbol.Name + ')' + GetReferenceString
  82. else
  83. GetReferenceString := symbol.Name + {'+' +} GetReferenceString;
  84. end;
  85. end
  86. else
  87. begin
  88. {$ifdef extdebug}
  89. if (Offset<>0) or assigned(symbol) then
  90. internalerror(2003052603);
  91. {$endif extdebug}
  92. GetReferenceString := GetReferenceString + '(' + gas_regname(index) + ')';
  93. end;
  94. end;
  95. end;
  96. end;
  97. function getopstr(const Oper: TOper): string;
  98. begin
  99. with Oper do
  100. case typ of
  101. top_reg:
  102. getopstr := gas_regname(reg);
  103. top_const:
  104. getopstr := tostr(longint(val));
  105. top_ref:
  106. if (oper.ref^.refaddr in [addr_no, addr_pic]) or ((oper.ref^.refaddr = addr_low) and ((oper.ref^.base <> NR_NO) or
  107. (oper.ref^.index <> NR_NO))) then
  108. getopstr := getreferencestring(ref^)
  109. else
  110. getopstr := getreferencestring(ref^);
  111. else
  112. internalerror(10001);
  113. end;
  114. end;
  115. function getopstr_4(const Oper: TOper): string;
  116. var
  117. tmpref: treference;
  118. begin
  119. with Oper do
  120. case typ of
  121. top_ref:
  122. begin
  123. tmpref := ref^;
  124. Inc(tmpref.offset, 4);
  125. getopstr_4 := getreferencestring(tmpref);
  126. end;
  127. else
  128. internalerror(2007050403);
  129. end;
  130. end;
  131. procedure TMIPSInstrWriter.WriteInstruction(hp: Tai);
  132. var
  133. Op: TAsmOp;
  134. s,s1: string;
  135. i: integer;
  136. tmpfpu: string;
  137. tmpfpu_len: longint;
  138. begin
  139. if hp.typ <> ait_instruction then
  140. exit;
  141. op := taicpu(hp).opcode;
  142. case op of
  143. A_P_STK2:
  144. begin
  145. s1 := getopstr(taicpu(hp).oper[2]^);
  146. STK2_LocalSize := align(STK2_LocalSize, 8);
  147. if s1[1] = '-' then
  148. str(-STK2_LocalSize, s1)
  149. else
  150. str(STK2_LocalSize, s1);
  151. s := #9 + gas_op2str[A_ADDIU] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[1]^) + ',' + s1;
  152. owner.AsmWriteLn(s);
  153. end;
  154. A_P_SET_MACRO:
  155. begin
  156. s := #9 + '.set' + #9 + 'macro';
  157. owner.AsmWriteLn(s);
  158. end;
  159. A_P_SET_REORDER:
  160. begin
  161. s := #9 + '.set' + #9 + 'reorder';
  162. owner.AsmWriteLn(s);
  163. end;
  164. A_P_SET_NOMACRO:
  165. begin
  166. s := #9 + '.set' + #9 + 'nomacro';
  167. owner.AsmWriteLn(s);
  168. end;
  169. A_P_SET_NOREORDER:
  170. begin
  171. s := #9 + '.set' + #9 + 'noreorder';
  172. owner.AsmWriteLn(s);
  173. end;
  174. A_P_SW:
  175. begin
  176. s := #9 + gas_op2str[A_SW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  177. owner.AsmWriteLn(s);
  178. end;
  179. A_P_LW:
  180. begin
  181. s := #9 + gas_op2str[A_LW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  182. owner.AsmWriteLn(s);
  183. end;
  184. A_LDC1:
  185. begin
  186. tmpfpu := getopstr(taicpu(hp).oper[0]^);
  187. s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  188. owner.AsmWriteLn(s);
  189. tmpfpu_len := length(tmpfpu);
  190. tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
  191. s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  192. owner.AsmWriteLn(s);
  193. end;
  194. A_SDC1:
  195. begin
  196. tmpfpu := getopstr(taicpu(hp).oper[0]^);
  197. s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  198. owner.AsmWriteLn(s);
  199. tmpfpu_len := length(tmpfpu);
  200. tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
  201. s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  202. owner.AsmWriteLn(s);
  203. end;
  204. else
  205. begin
  206. s := #9 + gas_op2str[op] + cond2str[taicpu(hp).condition];
  207. if taicpu(hp).delayslot_annulled then
  208. s := s + ',a';
  209. if taicpu(hp).ops > 0 then
  210. begin
  211. s := s + #9 + getopstr(taicpu(hp).oper[0]^);
  212. for i := 1 to taicpu(hp).ops - 1 do
  213. s := s + ',' + getopstr(taicpu(hp).oper[i]^);
  214. end;
  215. owner.AsmWriteLn(s);
  216. end;
  217. end;
  218. end;
  219. const
  220. as_MIPSEL_as_info: tasminfo =
  221. (
  222. id: as_gas;
  223. idtxt: 'AS';
  224. asmbin: 'as';
  225. asmcmd: '-mips2 -W -EL -o $OBJ $ASM';
  226. supported_targets: [system_mipsel_linux];
  227. flags: [af_allowdirect, af_needar, af_smartlink_sections];
  228. labelprefix: '.L';
  229. comment: '# ';
  230. dollarsign: '$';
  231. );
  232. as_MIPS_as_info: tasminfo =
  233. (
  234. id: as_gas;
  235. idtxt: 'AS';
  236. asmbin: 'as';
  237. asmcmd: '-mips2 -W -EB -o $OBJ $ASM';
  238. supported_targets: [system_mips_linux];
  239. flags: [af_allowdirect, af_needar, af_smartlink_sections];
  240. labelprefix: '.L';
  241. comment: '# ';
  242. dollarsign: '$';
  243. );
  244. begin
  245. {$ifdef MIPSEL}
  246. RegisterAssembler(as_MIPSEL_as_info, TMIPSGNUAssembler);
  247. {$else MIPSEL}
  248. RegisterAssembler(as_MIPS_as_info, TMIPSGNUAssembler);
  249. {$endif MIPSEL}
  250. end.