ncgmat.pas 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate generic mathematical 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 ncgmat;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nmat,cpubase,cgbase,cginfo;
  23. type
  24. tcgunaryminusnode = class(tunaryminusnode)
  25. procedure pass_2;override;
  26. { This routine is called to change the sign of the
  27. floating point value in the floating point
  28. register r.
  29. This routine should be overriden, since
  30. the generic version is not optimal at all. The
  31. generic version assumes that floating
  32. point values are stored in the register
  33. in IEEE-754 format.
  34. }
  35. procedure emit_float_sign_change(r: tregister; _size : tcgsize);virtual;
  36. end;
  37. implementation
  38. uses
  39. globtype,systems,
  40. cutils,verbose,globals,
  41. symconst,symdef,aasmbase,aasmtai,aasmcpu,defbase,
  42. pass_1,pass_2,
  43. ncon,
  44. cpuinfo,
  45. tgobj,ncgutil,cgobj,rgobj,rgcpu,cg64f32;
  46. {*****************************************************************************
  47. TCGUNARYMINUSNODE
  48. *****************************************************************************}
  49. procedure tcgunaryminusnode.emit_float_sign_change(r: tregister; _size : tcgsize);
  50. var
  51. href : treference;
  52. hreg : tregister;
  53. begin
  54. { get a temporary memory reference to store the floating
  55. point value
  56. }
  57. tg.gettempofsizereference(exprasmlist,tcgsize2size[_size],href);
  58. { store the floating point value in the temporary memory area }
  59. cg.a_loadfpu_reg_ref(exprasmlist,_size,r,href);
  60. { only single and double ieee are supported }
  61. if _size = OS_F64 then
  62. begin
  63. { on little-endian machine the most significant
  64. 32-bit value is stored at the highest address
  65. }
  66. if target_info.endian = endian_little then
  67. inc(href.offset,4);
  68. end
  69. else
  70. if _size <> OS_F32 then
  71. internalerror(20020814);
  72. hreg := rg.getregisterint(exprasmlist);
  73. { load value }
  74. cg.a_load_ref_reg(exprasmlist,OS_32,href,hreg);
  75. { bitwise complement copied value }
  76. cg.a_op_reg_reg(exprasmlist,OP_NOT,OS_32,hreg,hreg);
  77. { sign-bit is bit 31/63 of single/double }
  78. cg.a_op_const_reg(exprasmlist,OP_AND,$80000000,hreg);
  79. { or with value in reference memory }
  80. cg.a_op_reg_ref(exprasmlist,OP_OR,OS_32,hreg,href);
  81. rg.ungetregister(exprasmlist,hreg);
  82. { store the floating point value in the temporary memory area }
  83. if _size = OS_F64 then
  84. begin
  85. { on little-endian machine the most significant
  86. 32-bit value is stored at the highest address
  87. }
  88. if target_info.endian = endian_little then
  89. dec(href.offset,4);
  90. end;
  91. cg.a_loadfpu_ref_reg(exprasmlist,_size,href,r);
  92. end;
  93. procedure tcgunaryminusnode.pass_2;
  94. begin
  95. if is_64bitint(left.resulttype.def) then
  96. begin
  97. secondpass(left);
  98. { load left operator in a register }
  99. location_copy(location,left.location);
  100. location_force_reg(exprasmlist,location,OS_64,false);
  101. cg64.a_op64_loc_reg(exprasmlist,OP_NEG,
  102. location,joinreg64(location.registerlow,location.registerhigh));
  103. end
  104. else
  105. begin
  106. secondpass(left);
  107. location_reset(location,LOC_REGISTER,OS_INT);
  108. case left.location.loc of
  109. LOC_REGISTER:
  110. begin
  111. location.register:=left.location.register;
  112. cg.a_op_reg_reg(exprasmlist,OP_NEG,OS_INT,location.register,
  113. location.register);
  114. end;
  115. LOC_CREGISTER:
  116. begin
  117. location.register:=rg.getregisterint(exprasmlist);
  118. cg.a_load_reg_reg(exprasmlist,OS_INT,left.location.register,
  119. location.register);
  120. cg.a_op_reg_reg(exprasmlist,OP_NEG,OS_INT,location.register,
  121. location.register);
  122. end;
  123. LOC_REFERENCE,
  124. LOC_CREFERENCE:
  125. begin
  126. reference_release(exprasmlist,left.location.reference);
  127. if (left.resulttype.def.deftype=floatdef) then
  128. begin
  129. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  130. location.register:=rg.getregisterfpu(exprasmlist);
  131. cg.a_loadfpu_ref_reg(exprasmlist,
  132. def_cgsize(left.resulttype.def),
  133. left.location.reference,location.register);
  134. emit_float_sign_change(location.register,def_cgsize(left.resulttype.def));
  135. end
  136. else
  137. begin
  138. location.register:=rg.getregisterint(exprasmlist);
  139. { why is the size is OS_INT, since in pass_1 we convert
  140. everything to a signed natural value anyways
  141. }
  142. cg.a_load_ref_reg(exprasmlist,OS_INT,
  143. left.location.reference,location.register);
  144. cg.a_op_reg_reg(exprasmlist,OP_NEG,OS_INT,location.register,
  145. location.register);
  146. end;
  147. end;
  148. LOC_FPUREGISTER:
  149. begin
  150. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  151. location.register:=left.location.register;
  152. emit_float_sign_change(location.register,def_cgsize(left.resulttype.def));
  153. end;
  154. LOC_CFPUREGISTER:
  155. begin
  156. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  157. location.register:=rg.getregisterfpu(exprasmlist);
  158. cg.a_loadfpu_reg_reg(exprasmlist,left.location.register,location.register);
  159. emit_float_sign_change(location.register,def_cgsize(left.resulttype.def));
  160. end;
  161. else
  162. internalerror(200203225);
  163. end;
  164. end;
  165. end;
  166. begin
  167. cunaryminusnode:=tcgunaryminusnode;
  168. end.
  169. {
  170. $Log$
  171. Revision 1.1 2002-08-14 19:26:55 carl
  172. + generic int_to_real type conversion
  173. + generic unaryminus node
  174. }