1 { 2 Copyright (c) 1998-2011 by Florian Klaempfl and Jonas Maebe 3 4 Generate JVM code for math nodes 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 20 **************************************************************************** 21 } 22 unit njvmmat; 23 24 {$i fpcdefs.inc} 25 26 interface 27 28 uses 29 node,nmat,ncgmat,ncghlmat; 30 31 type 32 tjvmmoddivnode = class(tmoddivnode) 33 protected use_moddiv64bitint_helpernull34 function use_moddiv64bitint_helper: boolean; override; 35 public 36 procedure pass_generate_code;override; 37 end; 38 39 tjvmshlshrnode = class(tshlshrnode) 40 procedure pass_generate_code;override; 41 end; 42 43 tjvmnotnode = class(tcghlnotnode) 44 end; 45 46 tjvmunaryminusnode = class(tcgunaryminusnode) 47 procedure second_float;override; 48 end; 49 50 implementation 51 52 uses 53 globtype,systems,constexp, 54 cutils,verbose,globals,compinnr, 55 symconst,symdef, 56 aasmbase,aasmcpu,aasmtai,aasmdata, 57 defutil, 58 cgbase,cgobj,pass_2,procinfo, 59 ncon, 60 cpubase, 61 hlcgobj,hlcgcpu,cgutils; 62 63 {***************************************************************************** 64 tjvmmoddivnode 65 *****************************************************************************} 66 tjvmmoddivnode.use_moddiv64bitint_helpernull67 function tjvmmoddivnode.use_moddiv64bitint_helper: boolean; 68 begin 69 result:= 70 (left.resultdef.typ=orddef) and 71 (right.resultdef.typ=orddef) and 72 ((torddef(left.resultdef).ordtype=u64bit) or 73 (torddef(right.resultdef).ordtype=u64bit)); 74 end; 75 76 77 procedure tjvmmoddivnode.pass_generate_code; 78 var 79 tmpreg: tregister; 80 lab: tasmlabel; 81 ovloc: tlocation; 82 op: topcg; 83 isu32int: boolean; 84 begin 85 secondpass(left); 86 secondpass(right); 87 location_reset(location,LOC_REGISTER,left.location.size); 88 location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 89 90 91 if nodetype=divn then 92 begin 93 thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location); 94 if is_signed(resultdef) then 95 op:=OP_IDIV 96 else 97 op:=OP_DIV; 98 thlcgjvm(hlcg).a_op_loc_stack(current_asmdata.CurrAsmList,op,right.resultdef,right.location) 99 end 100 else 101 begin 102 { must be handled via a helper } 103 if torddef(resultdef).ordtype=u64bit then 104 internalerror(2011010416); 105 if (torddef(resultdef).ordtype<>u32bit) then 106 begin 107 isu32int:=false; 108 thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location); 109 thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location); 110 end 111 else 112 begin 113 isu32int:=true; 114 if left.location.loc=LOC_CONSTANT then 115 thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s64inttype,left.location.value,R_INTREGISTER) 116 else 117 begin 118 thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location); 119 thlcgjvm(hlcg).resize_stack_int_val(current_asmdata.CurrAsmList,u32inttype,s64inttype,false); 120 end; 121 if right.location.loc=LOC_CONSTANT then 122 thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s64inttype,right.location.value,R_INTREGISTER) 123 else 124 begin 125 thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location); 126 thlcgjvm(hlcg).resize_stack_int_val(current_asmdata.CurrAsmList,u32inttype,s64inttype,false); 127 end; 128 end; 129 if isu32int or 130 (torddef(resultdef).ordtype=s64bit) then 131 begin 132 current_asmdata.CurrAsmList.concat(taicpu.op_none(a_lrem)); 133 thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,2); 134 end 135 else 136 begin 137 current_asmdata.CurrAsmList.concat(taicpu.op_none(a_irem)); 138 thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1); 139 end; 140 if isu32int then 141 thlcgjvm(hlcg).resize_stack_int_val(current_asmdata.CurrAsmList,s64inttype,u32inttype,false); 142 end; 143 thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register); 144 if (cs_check_overflow in current_settings.localswitches) and 145 is_signed(resultdef) then 146 begin 147 { the JVM raises an exception for integer div-iby-zero -> only 148 overflow in case left is low(inttype) and right is -1 -> 149 check by adding high(inttype) to left and and'ing with right 150 -> result is -1 only in case above conditions are fulfilled) 151 } 152 tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 153 hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,true); 154 hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_ADD,resultdef,torddef(resultdef).high,right.location.register,tmpreg); 155 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true); 156 hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_AND,resultdef,left.location.register,tmpreg); 157 current_asmdata.getjumplabel(lab); 158 hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,resultdef,OC_NE,-1,tmpreg,lab); 159 hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_overflow',[],nil); 160 hlcg.a_label(current_asmdata.CurrAsmList,lab); 161 end; 162 end; 163 164 165 {***************************************************************************** 166 tjvmshlshrnode 167 *****************************************************************************} 168 169 procedure tjvmshlshrnode.pass_generate_code; 170 var 171 op : topcg; 172 begin 173 secondpass(left); 174 secondpass(right); 175 location_reset(location,LOC_REGISTER,left.location.size); 176 location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 177 178 thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location); 179 if nodetype=shln then 180 op:=OP_SHL 181 else 182 op:=OP_SHR; 183 thlcgjvm(hlcg).a_op_loc_stack(current_asmdata.CurrAsmList,op,resultdef,right.location); 184 thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register); 185 end; 186 187 188 {***************************************************************************** 189 tjvmunaryminustnode 190 *****************************************************************************} 191 192 procedure tjvmunaryminusnode.second_float; 193 var 194 opc: tasmop; 195 begin 196 secondpass(left); 197 location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef)); 198 location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef); 199 thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location); 200 if (tfloatdef(left.resultdef).floattype=s32real) then 201 opc:=a_fneg 202 else 203 opc:=a_dneg; 204 current_asmdata.CurrAsmList.concat(taicpu.op_none(opc)); 205 thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register); 206 end; 207 208 209 begin 210 cmoddivnode:=tjvmmoddivnode; 211 cshlshrnode:=tjvmshlshrnode; 212 cnotnode:=tjvmnotnode; 213 cunaryminusnode:=tjvmunaryminusnode; 214 end. 215