njvmmat.pas 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. {
  2. Copyright (c) 1998-2011 by Florian Klaempfl and Jonas Maebe
  3. Generate JVM code for math 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 njvmmat;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,nmat,ncgmat;
  22. type
  23. tjvmmoddivnode = class(tmoddivnode)
  24. protected
  25. function use_moddiv64bitint_helper: boolean; override;
  26. public
  27. procedure pass_generate_code;override;
  28. end;
  29. tjvmshlshrnode = class(tshlshrnode)
  30. procedure pass_generate_code;override;
  31. end;
  32. tjvmnotnode = class(tcgnotnode)
  33. procedure second_boolean;override;
  34. end;
  35. tjvmunaryminusnode = class(tcgunaryminusnode)
  36. procedure second_float;override;
  37. end;
  38. implementation
  39. uses
  40. globtype,systems,constexp,
  41. cutils,verbose,globals,
  42. symconst,symdef,
  43. aasmbase,aasmcpu,aasmtai,aasmdata,
  44. defutil,
  45. cgbase,cgobj,pass_2,procinfo,
  46. ncon,
  47. cpubase,
  48. hlcgobj,hlcgcpu,cgutils;
  49. {*****************************************************************************
  50. tjvmmoddivnode
  51. *****************************************************************************}
  52. function tjvmmoddivnode.use_moddiv64bitint_helper: boolean;
  53. begin
  54. result:=
  55. (left.resultdef.typ=orddef) and
  56. (right.resultdef.typ=orddef) and
  57. ((torddef(left.resultdef).ordtype=u64bit) or
  58. (torddef(right.resultdef).ordtype=u64bit));
  59. end;
  60. procedure tjvmmoddivnode.pass_generate_code;
  61. var
  62. op: topcg;
  63. isu32int: boolean;
  64. begin
  65. secondpass(left);
  66. secondpass(right);
  67. location_reset(location,LOC_REGISTER,left.location.size);
  68. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  69. if nodetype=divn then
  70. begin
  71. { TODO: overflow checking in case of high(longint) or high(int64) div -1 }
  72. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  73. if is_signed(resultdef) then
  74. op:=OP_IDIV
  75. else
  76. op:=OP_DIV;
  77. thlcgjvm(hlcg).a_op_loc_stack(current_asmdata.CurrAsmList,op,right.resultdef,right.location)
  78. end
  79. else
  80. begin
  81. { must be handled via a helper }
  82. if torddef(resultdef).ordtype=u64bit then
  83. internalerror(2011010416);
  84. if (torddef(resultdef).ordtype<>u32bit) then
  85. begin
  86. isu32int:=false;
  87. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  88. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);
  89. end
  90. else
  91. begin
  92. isu32int:=true;
  93. if left.location.loc=LOC_CONSTANT then
  94. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s64inttype,left.location.value,R_INTREGISTER)
  95. else
  96. begin
  97. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  98. thlcgjvm(hlcg).resize_stack_int_val(current_asmdata.CurrAsmList,OS_32,OS_S64,false);
  99. end;
  100. if right.location.loc=LOC_CONSTANT then
  101. thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s64inttype,right.location.value,R_INTREGISTER)
  102. else
  103. begin
  104. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);
  105. thlcgjvm(hlcg).resize_stack_int_val(current_asmdata.CurrAsmList,OS_32,OS_S64,false);
  106. end;
  107. end;
  108. if isu32int or
  109. (torddef(resultdef).ordtype=s64bit) then
  110. begin
  111. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_lrem));
  112. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,2);
  113. end
  114. else
  115. begin
  116. current_asmdata.CurrAsmList.concat(taicpu.op_none(a_irem));
  117. thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
  118. end;
  119. if isu32int then
  120. thlcgjvm(hlcg).resize_stack_int_val(current_asmdata.CurrAsmList,OS_S64,OS_32,false);
  121. end;
  122. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  123. end;
  124. {*****************************************************************************
  125. tjvmshlshrnode
  126. *****************************************************************************}
  127. procedure tjvmshlshrnode.pass_generate_code;
  128. var
  129. op : topcg;
  130. begin
  131. secondpass(left);
  132. secondpass(right);
  133. location_reset(location,LOC_REGISTER,left.location.size);
  134. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  135. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  136. if nodetype=shln then
  137. op:=OP_SHL
  138. else
  139. op:=OP_SHR;
  140. thlcgjvm(hlcg).a_op_loc_stack(current_asmdata.CurrAsmList,op,resultdef,right.location);
  141. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  142. end;
  143. {*****************************************************************************
  144. tjvmnotnode
  145. *****************************************************************************}
  146. procedure tjvmnotnode.second_boolean;
  147. var
  148. hl : tasmlabel;
  149. begin
  150. { if the location is LOC_JUMP, we do the secondpass after the
  151. labels are allocated
  152. }
  153. if left.expectloc=LOC_JUMP then
  154. begin
  155. hl:=current_procinfo.CurrTrueLabel;
  156. current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
  157. current_procinfo.CurrFalseLabel:=hl;
  158. secondpass(left);
  159. hlcg.maketojumpbool(current_asmdata.CurrAsmList,left);
  160. hl:=current_procinfo.CurrTrueLabel;
  161. current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
  162. current_procinfo.CurrFalseLabel:=hl;
  163. location.loc:=LOC_JUMP;
  164. end
  165. else
  166. begin
  167. secondpass(left);
  168. case left.location.loc of
  169. LOC_REGISTER, LOC_CREGISTER,
  170. LOC_REFERENCE, LOC_CREFERENCE:
  171. begin
  172. location_reset(location,LOC_REGISTER,left.location.size);
  173. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  174. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  175. thlcgjvm(hlcg).a_op_reg_stack(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,NR_NO);
  176. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  177. end;
  178. else
  179. internalerror(2011010417);
  180. end;
  181. end;
  182. end;
  183. procedure tjvmunaryminusnode.second_float;
  184. var
  185. opc: tasmop;
  186. begin
  187. secondpass(left);
  188. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  189. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  190. thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
  191. if (tfloatdef(left.resultdef).floattype=s32real) then
  192. opc:=a_fneg
  193. else
  194. opc:=a_dneg;
  195. current_asmdata.CurrAsmList.concat(taicpu.op_none(opc));
  196. thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
  197. end;
  198. begin
  199. cmoddivnode:=tjvmmoddivnode;
  200. cshlshrnode:=tjvmshlshrnode;
  201. cnotnode:=tjvmnotnode;
  202. cunaryminusnode:=tjvmunaryminusnode;
  203. end.