cgcpu.pas 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);override;
  31. end;
  32. implementation
  33. uses
  34. globtype,globals,verbose,systems,cutils,
  35. symdef,symsym,defbase,paramgr,
  36. rgobj,tgobj,rgcpu;
  37. procedure tcgx86_64.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);
  38. var
  39. ecxpushed : boolean;
  40. helpsize : longint;
  41. i : byte;
  42. reg8,reg32 : tregister;
  43. srcref,dstref : treference;
  44. swap : boolean;
  45. procedure maybepushecx;
  46. begin
  47. if not(R_ECX in rg.unusedregsint) then
  48. begin
  49. list.concat(Taicpu.Op_reg(A_PUSH,S_L,R_ECX));
  50. ecxpushed:=true;
  51. end
  52. else rg.getexplicitregisterint(list,R_ECX);
  53. end;
  54. begin
  55. if (not loadref) and
  56. ((len<=8) or
  57. (not(cs_littlesize in aktglobalswitches ) and (len<=12))) then
  58. begin
  59. helpsize:=len shr 3;
  60. rg.getexplicitregisterint(list,R_RDI);
  61. dstref:=dest;
  62. srcref:=source;
  63. for i:=1 to helpsize do
  64. begin
  65. a_load_ref_reg(list,OS_64,srcref,R_RDI);
  66. If (len=8) and delsource then
  67. reference_release(list,source);
  68. a_load_reg_ref(list,OS_64,R_RDI,dstref);
  69. inc(srcref.offset,8);
  70. inc(dstref.offset,8);
  71. dec(len,8);
  72. end;
  73. if len>1 then
  74. begin
  75. a_load_ref_reg(list,OS_16,srcref,R_EDI);
  76. If (len =4) and delsource then
  77. reference_release(list,source);
  78. a_load_reg_ref(list,OS_16,R_EDI,dstref);
  79. inc(srcref.offset,4);
  80. inc(dstref.offset,4);
  81. dec(len,4);
  82. end;
  83. if len>1 then
  84. begin
  85. a_load_ref_reg(list,OS_16,srcref,R_DI);
  86. If (len = 2) and delsource then
  87. reference_release(list,source);
  88. a_load_reg_ref(list,OS_16,R_DI,dstref);
  89. inc(srcref.offset,2);
  90. inc(dstref.offset,2);
  91. dec(len,2);
  92. end;
  93. if len>0 then
  94. begin
  95. a_load_ref_reg(list,OS_16,srcref,R_DIL);
  96. a_load_reg_ref(list,OS_16,R_DIL,dstref);
  97. end;
  98. rg.ungetregisterint(list,R_RDI);
  99. end
  100. else
  101. begin
  102. rg.getexplicitregisterint(list,R_RDI);
  103. a_loadaddr_ref_reg(list,dest,R_RDI);
  104. list.concat(tai_regalloc.Alloc(R_RSI));
  105. if loadref then
  106. a_load_ref_reg(list,OS_ADDR,source,R_RSI)
  107. else
  108. begin
  109. a_loadaddr_ref_reg(list,source,R_RSI);
  110. if delsource then
  111. reference_release(list,source);
  112. end;
  113. list.concat(Taicpu.Op_none(A_CLD,S_NO));
  114. ecxpushed:=false;
  115. if cs_littlesize in aktglobalswitches then
  116. begin
  117. maybepushecx;
  118. a_load_const_reg(list,OS_INT,len,R_RCX);
  119. list.concat(Taicpu.Op_none(A_REP,S_NO));
  120. list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
  121. end
  122. else
  123. begin
  124. helpsize:=len shr 2;
  125. len:=len and 3;
  126. if helpsize>1 then
  127. begin
  128. maybepushecx;
  129. a_load_const_reg(list,OS_INT,helpsize,R_RCX);
  130. list.concat(Taicpu.Op_none(A_REP,S_NO));
  131. end;
  132. if helpsize>0 then
  133. list.concat(Taicpu.Op_none(A_MOVSD,S_NO));
  134. if len>1 then
  135. begin
  136. dec(len,2);
  137. list.concat(Taicpu.Op_none(A_MOVSW,S_NO));
  138. end;
  139. if len=1 then
  140. list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
  141. end;
  142. rg.ungetregisterint(list,R_RDI);
  143. list.concat(tai_regalloc.DeAlloc(R_RSI));
  144. if ecxpushed then
  145. list.concat(Taicpu.Op_reg(A_POP,S_L,R_RCX))
  146. else
  147. rg.ungetregisterint(list,R_RCX);
  148. { loading SELF-reference again }
  149. g_maybe_loadself(list);
  150. end;
  151. if delsource then
  152. tg.ungetiftemp(list,source);
  153. end;
  154. begin
  155. cg:=tcgx86_64.create;
  156. cg64:=tcg64f64.create;
  157. end.
  158. {
  159. $Log$
  160. Revision 1.2 2002-07-25 22:55:33 florian
  161. * several fixes, small test units can be compiled
  162. Revision 1.1 2002/07/24 22:38:15 florian
  163. + initial release of x86-64 target code
  164. }