cpugas.pas 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. TGasMIPSEL = class(TGnuAssembler)
  25. procedure WriteInstruction(hp: Tai); override;
  26. end;
  27. implementation
  28. uses
  29. cutils, systems,
  30. verbose, itcpugas, cgbase, cgutils;
  31. function GetReferenceString(var ref: TReference): string;
  32. begin
  33. GetReferenceString := '';
  34. with ref do
  35. begin
  36. if (base = NR_NO) and (index = NR_NO) then
  37. begin
  38. if assigned(symbol) then
  39. GetReferenceString := symbol.Name;
  40. if offset > 0 then
  41. GetReferenceString := GetReferenceString + '+' + ToStr(offset)
  42. else if offset < 0 then
  43. GetReferenceString := GetReferenceString + ToStr(offset);
  44. case refaddr of
  45. addr_hi:
  46. GetReferenceString := '%hi(' + GetReferenceString + ')';
  47. addr_lo:
  48. GetReferenceString := '%lo(' + GetReferenceString + ')';
  49. end;
  50. end
  51. else
  52. begin
  53. {$ifdef extdebug}
  54. if assigned(symbol) and
  55. not(refaddr in [addr_pic,addr_lo]) then
  56. internalerror(2003052601);
  57. {$endif extdebug}
  58. if base <> NR_NO then
  59. GetReferenceString := GetReferenceString + '(' + gas_regname(base) + ')';
  60. if index = NR_NO then
  61. begin
  62. if offset <> 0 then
  63. GetReferenceString := ToStr(offset) + GetReferenceString;
  64. if assigned(symbol) then
  65. begin
  66. if refaddr = addr_lo then
  67. GetReferenceString := '%lo(' + symbol.Name + ')' + GetReferenceString
  68. else
  69. GetReferenceString := symbol.Name + {'+' +} GetReferenceString;
  70. end;
  71. end
  72. else
  73. begin
  74. {$ifdef extdebug}
  75. if (Offset<>0) or assigned(symbol) then
  76. internalerror(2003052603);
  77. {$endif extdebug}
  78. GetReferenceString := GetReferenceString + '(' + gas_regname(index) + ')';
  79. end;
  80. end;
  81. end;
  82. end;
  83. function getopstr(const Oper: TOper): string;
  84. begin
  85. with Oper do
  86. case typ of
  87. top_reg:
  88. getopstr := gas_regname(reg);
  89. top_const:
  90. getopstr := tostr(longint(val));
  91. top_ref:
  92. if (oper.ref^.refaddr in [addr_no, addr_pic]) or ((oper.ref^.refaddr = addr_lo) and ((oper.ref^.base <> NR_NO) or
  93. (oper.ref^.index <> NR_NO))) then
  94. getopstr := getreferencestring(ref^)
  95. else
  96. getopstr := getreferencestring(ref^);
  97. else
  98. internalerror(10001);
  99. end;
  100. end;
  101. function getopstr_4(const Oper: TOper): string;
  102. var
  103. tmpref: treference;
  104. begin
  105. with Oper do
  106. case typ of
  107. top_ref:
  108. begin
  109. tmpref := ref^;
  110. Inc(tmpref.offset, 4);
  111. getopstr_4 := getreferencestring(tmpref);
  112. end;
  113. else
  114. internalerror(2007050403);
  115. end;
  116. end;
  117. procedure TGasMIPSEL.WriteInstruction(hp: Tai);
  118. var
  119. Op: TAsmOp;
  120. s,s1: string;
  121. i: integer;
  122. tmpfpu: string;
  123. tmpfpu_len: longint;
  124. begin
  125. if hp.typ <> ait_instruction then
  126. exit;
  127. op := taicpu(hp).opcode;
  128. case op of
  129. A_P_STK2:
  130. begin
  131. s1 := getopstr(taicpu(hp).oper[2]^);
  132. STK2_LocalSize := align(STK2_LocalSize, 8);
  133. if s1[1] = '-' then
  134. str(-STK2_LocalSize, s1)
  135. else
  136. str(STK2_LocalSize, s1);
  137. s := #9 + std_op2str[A_ADDIU] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[1]^) + ',' + s1;
  138. AsmWriteLn(s);
  139. end;
  140. A_P_FRAME:
  141. begin
  142. end;
  143. A_P_SET_MACRO:
  144. begin
  145. s := #9 + '.set' + #9 + 'macro';
  146. AsmWriteLn(s);
  147. end;
  148. A_P_SET_REORDER:
  149. begin
  150. s := #9 + '.set' + #9 + 'reorder';
  151. AsmWriteLn(s);
  152. end;
  153. A_P_SET_NOMACRO:
  154. begin
  155. s := #9 + '.set' + #9 + 'nomacro';
  156. AsmWriteLn(s);
  157. end;
  158. A_P_SET_NOREORDER:
  159. begin
  160. s := #9 + '.set' + #9 + 'noreorder';
  161. AsmWriteLn(s);
  162. end;
  163. A_P_SW:
  164. begin
  165. s := #9 + std_op2str[A_SW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  166. AsmWriteLn(s);
  167. end;
  168. A_P_LW:
  169. begin
  170. s := #9 + std_op2str[A_LW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  171. AsmWriteLn(s);
  172. end;
  173. A_LDC1:
  174. begin
  175. tmpfpu := getopstr(taicpu(hp).oper[0]^);
  176. s := #9 + std_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  177. AsmWriteLn(s);
  178. tmpfpu_len := length(tmpfpu);
  179. tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
  180. s := #9 + std_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  181. AsmWriteLn(s);
  182. end;
  183. A_SDC1:
  184. begin
  185. tmpfpu := getopstr(taicpu(hp).oper[0]^);
  186. s := #9 + std_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  187. AsmWriteLn(s);
  188. tmpfpu_len := length(tmpfpu);
  189. tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
  190. s := #9 + std_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
  191. AsmWriteLn(s);
  192. end;
  193. else
  194. begin
  195. s := #9 + std_op2str[op] + cond2str[taicpu(hp).condition];
  196. if taicpu(hp).delayslot_annulled then
  197. s := s + ',a';
  198. if taicpu(hp).ops > 0 then
  199. begin
  200. s := s + #9 + getopstr(taicpu(hp).oper[0]^);
  201. for i := 1 to taicpu(hp).ops - 1 do
  202. s := s + ',' + getopstr(taicpu(hp).oper[i]^);
  203. end;
  204. AsmWriteLn(s);
  205. end;
  206. end;
  207. end;
  208. const
  209. as_MIPSEL_as_info: tasminfo =
  210. (
  211. id: as_gas;
  212. idtxt: 'AS';
  213. asmbin: 'as';
  214. asmcmd: '-mips2 -W -EL -o $OBJ $ASM';
  215. supported_target: system_any;
  216. flags: [af_allowdirect, af_needar, af_smartlink_sections];
  217. labelprefix: '.L';
  218. comment: '# ';
  219. );
  220. begin
  221. RegisterAssembler(as_MIPSEL_as_info, TGasMIPSEL);
  222. end.