cpugas.pas 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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_lo]) 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_FRAME:
  155. begin
  156. end;
  157. A_P_SET_MACRO:
  158. begin
  159. s := #9 + '.set' + #9 + 'macro';
  160. owner.AsmWriteLn(s);
  161. end;
  162. A_P_SET_REORDER:
  163. begin
  164. s := #9 + '.set' + #9 + 'reorder';
  165. owner.AsmWriteLn(s);
  166. end;
  167. A_P_SET_NOMACRO:
  168. begin
  169. s := #9 + '.set' + #9 + 'nomacro';
  170. owner.AsmWriteLn(s);
  171. end;
  172. A_P_SET_NOREORDER:
  173. begin
  174. s := #9 + '.set' + #9 + 'noreorder';
  175. owner.AsmWriteLn(s);
  176. end;
  177. A_P_SW:
  178. begin
  179. s := #9 + gas_op2str[A_SW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  180. owner.AsmWriteLn(s);
  181. end;
  182. A_P_LW:
  183. begin
  184. s := #9 + gas_op2str[A_LW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  185. owner.AsmWriteLn(s);
  186. end;
  187. A_LDC1:
  188. begin
  189. tmpfpu := getopstr(taicpu(hp).oper[0]^);
  190. s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  191. owner.AsmWriteLn(s);
  192. tmpfpu_len := length(tmpfpu);
  193. tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
  194. s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  195. owner.AsmWriteLn(s);
  196. end;
  197. A_SDC1:
  198. begin
  199. tmpfpu := getopstr(taicpu(hp).oper[0]^);
  200. s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  201. owner.AsmWriteLn(s);
  202. tmpfpu_len := length(tmpfpu);
  203. tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
  204. s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  205. owner.AsmWriteLn(s);
  206. end;
  207. else
  208. begin
  209. s := #9 + gas_op2str[op] + cond2str[taicpu(hp).condition];
  210. if taicpu(hp).delayslot_annulled then
  211. s := s + ',a';
  212. if taicpu(hp).ops > 0 then
  213. begin
  214. s := s + #9 + getopstr(taicpu(hp).oper[0]^);
  215. for i := 1 to taicpu(hp).ops - 1 do
  216. s := s + ',' + getopstr(taicpu(hp).oper[i]^);
  217. end;
  218. owner.AsmWriteLn(s);
  219. end;
  220. end;
  221. end;
  222. const
  223. as_MIPSEL_as_info: tasminfo =
  224. (
  225. id: as_gas;
  226. idtxt: 'AS';
  227. asmbin: 'as';
  228. asmcmd: '-mips2 -W -EL -o $OBJ $ASM';
  229. supported_targets: [system_mips_linux,system_mipsel_linux];
  230. flags: [af_allowdirect, af_needar, af_smartlink_sections];
  231. labelprefix: '.L';
  232. comment: '# ';
  233. );
  234. begin
  235. RegisterAssembler(as_MIPSEL_as_info, TMIPSGNUAssembler);
  236. end.