nllvmadd.pas 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. {
  2. Copyright (c) 2013 by Jonas Maebe
  3. Generate LLVM bytecode for add 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 nllvmadd;
  18. {$mode objfpc}
  19. interface
  20. uses
  21. node,
  22. ncgadd;
  23. type
  24. tllvmaddnode = class(tcgaddnode)
  25. public
  26. function pass_1: tnode; override;
  27. protected
  28. procedure second_cmpsmallset; override;
  29. procedure second_cmpordinal; override;
  30. procedure second_add64bit; override;
  31. procedure second_cmp64bit; override;
  32. procedure second_addfloat; override;
  33. end;
  34. implementation
  35. uses
  36. verbose,globtype,
  37. aasmdata,
  38. symtype,symdef,defutil,
  39. llvmbase,aasmllvm,
  40. cgbase,cgutils,
  41. hlcgobj,
  42. nadd
  43. ;
  44. { tllvmaddnode }
  45. function tllvmaddnode.pass_1: tnode;
  46. begin
  47. result:=inherited pass_1;
  48. { there are no flags in LLVM }
  49. if expectloc=LOC_FLAGS then
  50. expectloc:=LOC_REGISTER;
  51. end;
  52. procedure tllvmaddnode.second_cmpsmallset;
  53. var
  54. tmpreg,
  55. tmpreg2: tregister;
  56. cmpop : topcmp;
  57. begin
  58. pass_left_right;
  59. location_reset(location,LOC_REGISTER,OS_8);
  60. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,pasbool8type);
  61. force_reg_left_right(false,false);
  62. case nodetype of
  63. equaln,
  64. unequaln:
  65. begin
  66. if nodetype=equaln then
  67. cmpop:=OC_EQ
  68. else
  69. cmpop:=OC_NE;
  70. current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,
  71. location.register,cmpop,left.resultdef,left.location.register,right.location.register));
  72. end;
  73. lten,
  74. gten:
  75. begin
  76. if (not(nf_swapped in flags) and
  77. (nodetype = lten)) or
  78. ((nf_swapped in flags) and
  79. (nodetype = gten)) then
  80. swapleftright;
  81. { set1<=set2 <-> set2 and not(set1) = 0 }
  82. tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef);
  83. hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,left.location.register,tmpreg);
  84. tmpreg2:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef);
  85. hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,left.resultdef,right.location.register,tmpreg,tmpreg2);
  86. current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,
  87. location.register,OC_EQ,left.resultdef,tmpreg2,0));
  88. end;
  89. else
  90. internalerror(2012042701);
  91. end;
  92. end;
  93. procedure tllvmaddnode.second_cmpordinal;
  94. var
  95. cmpop: topcmp;
  96. unsigned : boolean;
  97. begin
  98. pass_left_right;
  99. force_reg_left_right(true,true);
  100. unsigned:=not(is_signed(left.resultdef)) or
  101. not(is_signed(right.resultdef));
  102. case nodetype of
  103. ltn:
  104. if unsigned then
  105. cmpop:=OC_B
  106. else
  107. cmpop:=OC_LT;
  108. lten:
  109. if unsigned then
  110. cmpop:=OC_BE
  111. else
  112. cmpop:=OC_LTE;
  113. gtn:
  114. if unsigned then
  115. cmpop:=OC_A
  116. else
  117. cmpop:=OC_GT;
  118. gten:
  119. if unsigned then
  120. cmpop:=OC_AE
  121. else
  122. cmpop:=OC_GTE;
  123. equaln:
  124. cmpop:=OC_EQ;
  125. unequaln:
  126. cmpop:=OC_NE;
  127. end;
  128. if nf_swapped in flags then
  129. cmpop:=swap_opcmp(cmpop);
  130. location_reset(location,LOC_REGISTER,OS_8);
  131. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  132. if right.location.loc=LOC_CONSTANT then
  133. current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,
  134. location.register,cmpop,left.resultdef,left.location.register,right.location.value64))
  135. else
  136. current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,
  137. location.register,cmpop,left.resultdef,left.location.register,right.location.register));
  138. end;
  139. procedure tllvmaddnode.second_add64bit;
  140. begin
  141. second_addordinal;
  142. end;
  143. procedure tllvmaddnode.second_cmp64bit;
  144. begin
  145. second_cmpordinal;
  146. end;
  147. procedure tllvmaddnode.second_addfloat;
  148. var
  149. op : tllvmop;
  150. llvmfpcmp : tllvmfpcmp;
  151. size : tdef;
  152. cmpop,
  153. singleprec : boolean;
  154. begin
  155. pass_left_right;
  156. cmpop:=false;
  157. singleprec:=tfloatdef(left.resultdef).floattype=s32real;
  158. case nodetype of
  159. addn :
  160. op:=la_fadd;
  161. muln :
  162. op:=la_fmul;
  163. subn :
  164. op:=la_fsub;
  165. slashn :
  166. op:=la_fdiv;
  167. ltn,lten,gtn,gten,
  168. equaln,unequaln :
  169. begin
  170. op:=la_fcmp;
  171. cmpop:=true;
  172. case nodetype of
  173. ltn:
  174. llvmfpcmp:=lfc_olt;
  175. lten:
  176. llvmfpcmp:=lfc_ole;
  177. gtn:
  178. llvmfpcmp:=lfc_ogt;
  179. gten:
  180. llvmfpcmp:=lfc_oge;
  181. equaln:
  182. llvmfpcmp:=lfc_oeq;
  183. unequaln:
  184. llvmfpcmp:=lfc_one;
  185. end;
  186. end;
  187. else
  188. internalerror(2013102401);
  189. end;
  190. { get the operands in the correct order; there are no special cases here,
  191. everything is register-based }
  192. if nf_swapped in flags then
  193. swapleftright;
  194. { put both operands in a register }
  195. hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
  196. hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  197. { initialize the result location }
  198. if not cmpop then
  199. begin
  200. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  201. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  202. end
  203. else
  204. begin
  205. location_reset(location,LOC_REGISTER,OS_8);
  206. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  207. end;
  208. { see comment in thlcgllvm.a_loadfpu_ref_reg }
  209. if tfloatdef(left.resultdef).floattype in [s64comp,s64currency] then
  210. size:=sc80floattype
  211. else
  212. size:=left.resultdef;
  213. { emit the actual operation }
  214. if not cmpop then
  215. begin
  216. current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_reg_reg(op,location.register,size,
  217. left.location.register,right.location.register))
  218. end
  219. else
  220. begin
  221. current_asmdata.CurrAsmList.concat(taillvm.op_reg_fpcond_size_reg_reg(op,
  222. location.register,llvmfpcmp,size,left.location.register,right.location.register))
  223. end;
  224. end;
  225. begin
  226. caddnode:=tllvmaddnode;
  227. end.