ncpumem.pas 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. {
  2. Copyright (c) 2014 by Jonas Maebe
  3. Generate AArch64 code for in memory related nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ncpumem;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. cgbase,
  23. symtype,
  24. node,nmem,ncgmem;
  25. type
  26. taarch64loadparentfpnode = class(tcgloadparentfpnode)
  27. procedure pass_generate_code; override;
  28. end;
  29. taarch64vecnode = class(tcgvecnode)
  30. protected
  31. function valid_index_size(size: tcgsize): boolean; override;
  32. public
  33. procedure update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint); override;
  34. end;
  35. implementation
  36. uses
  37. cutils,verbose,
  38. defutil,
  39. aasmdata,cpubase,
  40. cgutils,
  41. cgobj;
  42. { taarch64loadparentfpnode }
  43. procedure taarch64loadparentfpnode.pass_generate_code;
  44. begin
  45. inherited pass_generate_code;
  46. { see the comments in tcgaarch64.g_proc_entry }
  47. if (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
  48. (location.register=NR_STACK_POINTER_REG) then
  49. if (kind=lpf_forpara) then
  50. location.register:=NR_FRAME_POINTER_REG
  51. else
  52. begin
  53. { load stack pointer in a different register, as many instructions
  54. cannot directly work with the stack pointer. The register
  55. allocator can merge them if possible }
  56. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  57. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_STACK_POINTER_REG,location.register);
  58. location.loc:=LOC_REGISTER;
  59. end;
  60. end;
  61. { taarch64vecnode }
  62. function taarch64vecnode.valid_index_size(size: tcgsize): boolean;
  63. begin
  64. { all sizes are ok if we handle the "reference reg mul", because
  65. a) we use a 64 bit register for 64 bit values, and a 32 bit one (that
  66. we can sign/zero-extend inside the reference) for smaller values
  67. b) for values < 32 bit, the entire 32 bit register always contains the
  68. sign/zero-extended version of the value }
  69. result:=
  70. not is_packed_array(left.resultdef) and
  71. (get_mul_size in [1,2,4,8,16]);
  72. end;
  73. procedure taarch64vecnode.update_reference_reg_mul(maybe_const_reg: tregister; regsize: tdef; l: aint);
  74. var
  75. base: tregister;
  76. oldoffset: asizeint;
  77. shift: byte;
  78. begin
  79. { we can only scale the index by shl 0..4 }
  80. if not(l in [1,2,4,8,16]) then
  81. begin
  82. inherited;
  83. exit;
  84. end;
  85. { we need a base set and an index available }
  86. if (location.reference.base=NR_NO) or
  87. (location.reference.index<>NR_NO) then
  88. begin
  89. { don't integrate the offset yet, make_simple_ref() may be able to
  90. handle it more efficiently later (unless an offset is all we have
  91. -> optimization for someone that wants to add support for AArch64
  92. embedded targets) }
  93. oldoffset:=location.reference.offset;
  94. location.reference.offset:=0;
  95. base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  96. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,base);
  97. reference_reset_base(location.reference,base,oldoffset,location.reference.temppos,location.reference.alignment,location.reference.volatility);
  98. end;
  99. shift:=BsfDWord(l);
  100. location.reference.index:=maybe_const_reg;
  101. { sign/zero-extend? }
  102. if regsize.size=8 then
  103. if shift<>0 then
  104. location.reference.shiftmode:=SM_LSL
  105. else
  106. location.reference.shiftmode:=SM_NONE
  107. else if is_signed(regsize) then
  108. location.reference.shiftmode:=SM_SXTW
  109. else if shift<>0 then
  110. location.reference.shiftmode:=SM_UXTW
  111. else
  112. { the upper 32 bits are always already zero-extended -> just use 64 bit
  113. register }
  114. location.reference.index:=cg.makeregsize(current_asmdata.CurrAsmList,location.reference.index,OS_64);
  115. location.reference.shiftimm:=shift;
  116. location.reference.alignment:=newalignment(location.reference.alignment,l);
  117. end;
  118. begin
  119. cloadparentfpnode:=taarch64loadparentfpnode;
  120. cvecnode:=taarch64vecnode;
  121. end.