nx86mat.pas 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate x86 code for math nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit nx86mat;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nmat,ncgmat;
  23. type
  24. tx86unaryminusnode = class(tcgunaryminusnode)
  25. {$ifdef SUPPORT_MMX}
  26. procedure second_mmx;override;
  27. {$endif SUPPORT_MMX}
  28. procedure second_float;override;
  29. function pass_1:tnode;override;
  30. end;
  31. implementation
  32. uses
  33. globtype,systems,
  34. cutils,verbose,globals,
  35. symconst,symdef,aasmbase,aasmtai,defutil,
  36. cgbase,pass_1,pass_2,
  37. ncon,
  38. cpubase,cpuinfo,
  39. cga,ncgutil,cgobj,cgx86;
  40. {*****************************************************************************
  41. TI386UNARYMINUSNODE
  42. *****************************************************************************}
  43. function tx86unaryminusnode.pass_1 : tnode;
  44. begin
  45. result:=nil;
  46. firstpass(left);
  47. if codegenerror then
  48. exit;
  49. if (left.resulttype.def.deftype=floatdef) then
  50. begin
  51. if use_sse(left.resulttype.def) then
  52. begin
  53. if (registersmm < 1) then
  54. registersmm := 1;
  55. expectloc:=LOC_MMREGISTER;
  56. end
  57. else
  58. begin
  59. if (registersfpu < 1) then
  60. registersfpu := 1;
  61. expectloc:=LOC_FPUREGISTER;
  62. end;
  63. end
  64. {$ifdef SUPPORT_MMX}
  65. else
  66. if (cs_mmx in aktlocalswitches) and
  67. is_mmx_able_array(left.resulttype.def) then
  68. begin
  69. registers32:=left.registers32;
  70. registersfpu:=left.registersfpu;
  71. registersmmx:=left.registersmmx;
  72. if (left.location.loc<>LOC_MMXREGISTER) and
  73. (registersmmx<1) then
  74. registersmmx:=1;
  75. end
  76. {$endif SUPPORT_MMX}
  77. else
  78. inherited pass_1;
  79. end;
  80. {$ifdef SUPPORT_MMX}
  81. procedure tx86unaryminusnode.second_mmx;
  82. var
  83. op : tasmop;
  84. hreg : tregister;
  85. begin
  86. secondpass(left);
  87. location_reset(location,LOC_MMXREGISTER,OS_NO);
  88. hreg:=cg.getmmxregister(exprasmlist,OS_M64);
  89. emit_reg_reg(A_PXOR,S_NO,hreg,hreg);
  90. case left.location.loc of
  91. LOC_MMXREGISTER:
  92. begin
  93. location.register:=left.location.register;
  94. end;
  95. LOC_CMMXREGISTER:
  96. begin
  97. location.register:=cg.getmmxregister(exprasmlist,OS_M64);
  98. emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
  99. end;
  100. LOC_REFERENCE,
  101. LOC_CREFERENCE:
  102. begin
  103. reference_release(exprasmlist,left.location.reference);
  104. location.register:=cg.getmmxregister(exprasmlist,OS_M64);
  105. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
  106. end;
  107. else
  108. internalerror(200203225);
  109. end;
  110. if cs_mmx_saturation in aktlocalswitches then
  111. case mmx_type(resulttype.def) of
  112. mmxs8bit:
  113. op:=A_PSUBSB;
  114. mmxu8bit:
  115. op:=A_PSUBUSB;
  116. mmxs16bit,mmxfixed16:
  117. op:=A_PSUBSW;
  118. mmxu16bit:
  119. op:=A_PSUBUSW;
  120. end
  121. else
  122. case mmx_type(resulttype.def) of
  123. mmxs8bit,mmxu8bit:
  124. op:=A_PSUBB;
  125. mmxs16bit,mmxu16bit,mmxfixed16:
  126. op:=A_PSUBW;
  127. mmxs32bit,mmxu32bit:
  128. op:=A_PSUBD;
  129. end;
  130. emit_reg_reg(op,S_NO,location.register,hreg);
  131. cg.ungetregister(exprasmlist,hreg);
  132. emit_reg_reg(A_MOVQ,S_NO,hreg,location.register);
  133. end;
  134. {$endif SUPPORT_MMX}
  135. procedure tx86unaryminusnode.second_float;
  136. var
  137. reg : tregister;
  138. begin
  139. secondpass(left);
  140. if expectloc=LOC_MMREGISTER then
  141. begin
  142. reg:=cg.getmmregister(exprasmlist,OS_M128);
  143. { zero out the register
  144. op size doesn't matter }
  145. cg.a_opmm_reg_reg(exprasmlist,OP_XOR,OS_F32,reg,reg,nil);
  146. { move to a mm compatible location }
  147. if left.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
  148. location_force_mem(exprasmlist,left.location);
  149. cg.a_opmm_loc_reg(exprasmlist,OP_SUB,left.location.size,left.location,reg,mms_movescalar);
  150. location_release(exprasmlist,left.location);
  151. location_reset(location,LOC_MMREGISTER,def_cgsize(resulttype.def));
  152. location.register:=reg;
  153. end
  154. else
  155. begin
  156. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  157. case left.location.loc of
  158. LOC_REFERENCE,
  159. LOC_CREFERENCE:
  160. begin
  161. reference_release(exprasmlist,left.location.reference);
  162. location.register:=NR_ST;
  163. cg.a_loadfpu_ref_reg(exprasmlist,
  164. def_cgsize(left.resulttype.def),
  165. left.location.reference,location.register);
  166. emit_none(A_FCHS,S_NO);
  167. end;
  168. LOC_FPUREGISTER,
  169. LOC_CFPUREGISTER:
  170. begin
  171. { "load st,st" is ignored by the code generator }
  172. cg.a_loadfpu_reg_reg(exprasmlist,left.location.size,left.location.register,NR_ST);
  173. location.register:=NR_ST;
  174. emit_none(A_FCHS,S_NO);
  175. end;
  176. else
  177. internalerror(200312241);
  178. end;
  179. end;
  180. end;
  181. end.
  182. {
  183. $Log$
  184. Revision 1.1 2003-12-26 13:47:41 florian
  185. * rtl and compiler compile with -Cfsse2
  186. }