cgcpu.pas 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. {
  2. $Id$
  3. Copyright (c) 2002 by Florian Klaempfl
  4. This unit implements the code generator for the x86-64.
  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. { This unit implements the code generator for the x86-64.
  19. }
  20. unit cgcpu;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. cginfo,cgbase,cgobj,cg64f64,cgx86,
  25. aasmbase,aasmtai,aasmcpu,
  26. cpubase,cpuinfo,cpupara,
  27. node,symconst;
  28. type
  29. tcgx86_64 = class(tcgx86)
  30. class function reg_cgsize(const reg: tregister): tcgsize; override;
  31. procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);override;
  32. end;
  33. implementation
  34. uses
  35. globtype,globals,verbose,systems,cutils,
  36. symdef,symsym,defutil,paramgr,
  37. rgobj,tgobj,rgcpu;
  38. class function tcgx86_64.reg_cgsize(const reg: tregister): tcgsize;
  39. const
  40. opsize_2_cgsize: array[topsize] of tcgsize = (OS_NO,
  41. OS_8,OS_16,OS_32,OS_NO,OS_NO,OS_NO,OS_NO,OS_NO,OS_NO,
  42. OS_32,OS_64,OS_64,
  43. OS_F32,OS_F64,OS_F80,OS_F32,OS_F64,OS_NO,OS_NO,
  44. OS_NO,OS_NO,OS_NO
  45. );
  46. begin
  47. result := opsize_2_cgsize[reg2opsize(reg)];
  48. end;
  49. procedure tcgx86_64.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);
  50. var
  51. ecxpushed : boolean;
  52. helpsize : longint;
  53. i : byte;
  54. reg8,reg32 : tregister;
  55. srcref,dstref : treference;
  56. swap : boolean;
  57. {!!!
  58. procedure maybepushecx;
  59. begin
  60. if not(R_ECX in rg.unusedregsint) then
  61. begin
  62. list.concat(Taicpu.Op_reg(A_PUSH,S_L,R_ECX));
  63. ecxpushed:=true;
  64. end
  65. else rg.getexplicitregisterint(list,R_ECX);
  66. end;
  67. }
  68. begin
  69. {!!!
  70. if (not loadref) and
  71. ((len<=8) or
  72. (not(cs_littlesize in aktglobalswitches ) and (len<=12))) then
  73. begin
  74. helpsize:=len shr 3;
  75. rg.getexplicitregisterint(list,R_RDI);
  76. dstref:=dest;
  77. srcref:=source;
  78. for i:=1 to helpsize do
  79. begin
  80. a_load_ref_reg(list,OS_64,srcref,R_RDI);
  81. If (len=8) and delsource then
  82. reference_release(list,source);
  83. a_load_reg_ref(list,OS_64,R_RDI,dstref);
  84. inc(srcref.offset,8);
  85. inc(dstref.offset,8);
  86. dec(len,8);
  87. end;
  88. if len>1 then
  89. begin
  90. a_load_ref_reg(list,OS_16,srcref,R_EDI);
  91. If (len =4) and delsource then
  92. reference_release(list,source);
  93. a_load_reg_ref(list,OS_16,R_EDI,dstref);
  94. inc(srcref.offset,4);
  95. inc(dstref.offset,4);
  96. dec(len,4);
  97. end;
  98. if len>1 then
  99. begin
  100. a_load_ref_reg(list,OS_16,srcref,R_DI);
  101. If (len = 2) and delsource then
  102. reference_release(list,source);
  103. a_load_reg_ref(list,OS_16,R_DI,dstref);
  104. inc(srcref.offset,2);
  105. inc(dstref.offset,2);
  106. dec(len,2);
  107. end;
  108. if len>0 then
  109. begin
  110. a_load_ref_reg(list,OS_16,srcref,R_DIL);
  111. a_load_reg_ref(list,OS_16,R_DIL,dstref);
  112. end;
  113. rg.ungetregisterint(list,R_RDI);
  114. end
  115. else
  116. begin
  117. rg.getexplicitregisterint(list,R_RDI);
  118. a_loadaddr_ref_reg(list,dest,R_RDI);
  119. list.concat(tai_regalloc.Alloc(R_RSI));
  120. if loadref then
  121. a_load_ref_reg(list,OS_ADDR,source,R_RSI)
  122. else
  123. begin
  124. a_loadaddr_ref_reg(list,source,R_RSI);
  125. if delsource then
  126. reference_release(list,source);
  127. end;
  128. list.concat(Taicpu.Op_none(A_CLD,S_NO));
  129. ecxpushed:=false;
  130. if cs_littlesize in aktglobalswitches then
  131. begin
  132. maybepushecx;
  133. a_load_const_reg(list,OS_INT,len,R_RCX);
  134. list.concat(Taicpu.Op_none(A_REP,S_NO));
  135. list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
  136. end
  137. else
  138. begin
  139. helpsize:=len shr 2;
  140. len:=len and 3;
  141. if helpsize>1 then
  142. begin
  143. maybepushecx;
  144. a_load_const_reg(list,OS_INT,helpsize,R_RCX);
  145. list.concat(Taicpu.Op_none(A_REP,S_NO));
  146. end;
  147. if helpsize>0 then
  148. list.concat(Taicpu.Op_none(A_MOVSD,S_NO));
  149. if len>1 then
  150. begin
  151. dec(len,2);
  152. list.concat(Taicpu.Op_none(A_MOVSW,S_NO));
  153. end;
  154. if len=1 then
  155. list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
  156. end;
  157. rg.ungetregisterint(list,R_RDI);
  158. list.concat(tai_regalloc.DeAlloc(R_RSI));
  159. if ecxpushed then
  160. list.concat(Taicpu.Op_reg(A_POP,S_L,R_RCX))
  161. else
  162. rg.ungetregisterint(list,R_RCX);
  163. { loading SELF-reference again }
  164. g_maybe_loadself(list);
  165. end;
  166. if delsource then
  167. tg.ungetiftemp(list,source);
  168. }
  169. end;
  170. begin
  171. cg:=tcgx86_64.create;
  172. cg64:=tcg64f64.create;
  173. end.
  174. {
  175. $Log$
  176. Revision 1.5 2003-09-25 13:13:32 florian
  177. * more x86-64 fixes
  178. Revision 1.4 2003/04/30 15:45:35 florian
  179. * merged more x86-64/i386 code
  180. Revision 1.3 2003/01/05 13:36:54 florian
  181. * x86-64 compiles
  182. + very basic support for float128 type (x86-64 only)
  183. Revision 1.2 2002/07/25 22:55:33 florian
  184. * several fixes, small test units can be compiled
  185. Revision 1.1 2002/07/24 22:38:15 florian
  186. + initial release of x86-64 target code
  187. }