nx64mat.pas 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate x86-64 assembler 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 nx64mat;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nmat,ncgmat,nx86mat;
  23. type
  24. tx8664moddivnode = class(tmoddivnode)
  25. procedure pass_2;override;
  26. end;
  27. tx8664shlshrnode = class(tshlshrnode)
  28. procedure pass_2;override;
  29. end;
  30. tx8664unaryminusnode = class(tx86unaryminusnode)
  31. end;
  32. tx8664notnode = class(tx86notnode)
  33. end;
  34. implementation
  35. uses
  36. globtype,systems,
  37. cutils,verbose,globals,
  38. symconst,symdef,aasmbase,aasmtai,defutil,
  39. cgbase,pass_1,pass_2,
  40. ncon,
  41. cpubase,cpuinfo,
  42. cga,ncgutil,cgobj;
  43. {*****************************************************************************
  44. TX8664MODDIVNODE
  45. *****************************************************************************}
  46. procedure tx8664moddivnode.pass_2;
  47. var
  48. hreg1,hreg2:Tregister;
  49. power:longint;
  50. op:Tasmop;
  51. begin
  52. secondpass(left);
  53. if codegenerror then
  54. exit;
  55. secondpass(right);
  56. if codegenerror then
  57. exit;
  58. { put numerator in register }
  59. location_reset(location,LOC_REGISTER,OS_INT);
  60. location_force_reg(exprasmlist,left.location,OS_INT,false);
  61. hreg1:=left.location.register;
  62. if (nodetype=divn) and (right.nodetype=ordconstn) and
  63. ispowerof2(tordconstnode(right).value,power) then
  64. begin
  65. { for signed numbers, the numerator must be adjusted before the
  66. shift instruction, but not wih unsigned numbers! Otherwise,
  67. "Cardinal($ffffffff) div 16" overflows! (JM) }
  68. if is_signed(left.resulttype.def) Then
  69. begin
  70. { use a sequence without jumps, saw this in
  71. comp.compilers (JM) }
  72. { no jumps, but more operations }
  73. hreg2:=cg.getintregister(exprasmlist,OS_INT);
  74. emit_reg_reg(A_MOV,S_Q,hreg1,hreg2);
  75. {If the left value is signed, hreg2=$ffffffff, otherwise 0.}
  76. emit_const_reg(A_SAR,S_Q,63,hreg2);
  77. {If signed, hreg2=right value-1, otherwise 0.}
  78. emit_const_reg(A_AND,S_Q,tordconstnode(right).value-1,hreg2);
  79. { add to the left value }
  80. emit_reg_reg(A_ADD,S_Q,hreg2,hreg1);
  81. { release EDX if we used it }
  82. cg.ungetregister(exprasmlist,hreg2);
  83. { do the shift }
  84. emit_const_reg(A_SAR,S_Q,power,hreg1);
  85. end
  86. else
  87. emit_const_reg(A_SHR,S_Q,power,hreg1);
  88. location.register:=hreg1;
  89. end
  90. else
  91. begin
  92. {Bring denominator to a register.}
  93. cg.ungetregister(exprasmlist,hreg1);
  94. cg.getexplicitregister(exprasmlist,NR_RAX);
  95. emit_reg_reg(A_MOV,S_Q,hreg1,NR_RAX);
  96. cg.getexplicitregister(exprasmlist,NR_RDX);
  97. {Sign extension depends on the left type.}
  98. if torddef(left.resulttype.def).typ=u64bit then
  99. emit_reg_reg(A_XOR,S_Q,NR_RDX,NR_RDX)
  100. else
  101. emit_none(A_CDQ,S_NO);
  102. {Division depends on the right type.}
  103. if Torddef(right.resulttype.def).typ=u64bit then
  104. op:=A_DIV
  105. else
  106. op:=A_IDIV;
  107. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  108. emit_ref(op,S_Q,right.location.reference)
  109. else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  110. emit_reg(op,S_Q,right.location.register)
  111. else
  112. begin
  113. hreg1:=cg.getintregister(exprasmlist,right.location.size);
  114. cg.a_load_loc_reg(exprasmlist,OS_64,right.location,hreg1);
  115. cg.ungetregister(exprasmlist,hreg1);
  116. emit_reg(op,S_Q,hreg1);
  117. end;
  118. location_release(exprasmlist,right.location);
  119. { Copy the result into a new register. Release RAX & RDX.}
  120. if nodetype=divn then
  121. begin
  122. cg.ungetregister(exprasmlist,NR_RDX);
  123. cg.ungetregister(exprasmlist,NR_RAX);
  124. location.register:=cg.getintregister(exprasmlist,OS_INT);
  125. emit_reg_reg(A_MOV,S_Q,NR_RAX,location.register);
  126. end
  127. else
  128. begin
  129. cg.ungetregister(exprasmlist,NR_RAX);
  130. cg.ungetregister(exprasmlist,NR_RDX);
  131. location.register:=cg.getintregister(exprasmlist,OS_INT);
  132. emit_reg_reg(A_MOV,S_Q,NR_RDX,location.register);
  133. end;
  134. end;
  135. end;
  136. {*****************************************************************************
  137. TX8664SHLRSHRNODE
  138. *****************************************************************************}
  139. procedure tx8664shlshrnode.pass_2;
  140. var
  141. op : Tasmop;
  142. begin
  143. secondpass(left);
  144. secondpass(right);
  145. { determine operator }
  146. if nodetype=shln then
  147. op:=A_SHL
  148. else
  149. op:=A_SHR;
  150. { load left operators in a register }
  151. location_copy(location,left.location);
  152. location_force_reg(exprasmlist,location,OS_INT,false);
  153. { shifting by a constant directly coded: }
  154. if (right.nodetype=ordconstn) then
  155. { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)}
  156. emit_const_reg(op,S_Q,tordconstnode(right).value and 63,location.register)
  157. else
  158. begin
  159. { load right operators in a RCX }
  160. if right.location.loc<>LOC_CREGISTER then
  161. location_release(exprasmlist,right.location);
  162. cg.getexplicitregister(exprasmlist,NR_RCX);
  163. cg.a_load_loc_reg(exprasmlist,OS_64,right.location,NR_RCX);
  164. { right operand is in ECX }
  165. cg.ungetregister(exprasmlist,NR_RCX);
  166. emit_reg_reg(op,S_Q,NR_CL,location.register);
  167. end;
  168. end;
  169. begin
  170. cunaryminusnode:=tx8664unaryminusnode;
  171. cmoddivnode:=tx8664moddivnode;
  172. cshlshrnode:=tx8664shlshrnode;
  173. cnotnode:=tx8664notnode;
  174. end.
  175. {
  176. $Log$
  177. Revision 1.4 2004-02-05 18:28:37 peter
  178. * x86_64 fixes for opsize
  179. Revision 1.3 2004/02/05 01:24:08 florian
  180. * several fixes to compile x86-64 system
  181. Revision 1.2 2004/02/04 19:22:27 peter
  182. *** empty log message ***
  183. Revision 1.1 2004/01/20 12:59:37 florian
  184. * common addnode code for x86-64 and i386
  185. }