001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.opt.lir2mir.ia32; 014 015import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_2INT_opcode; 016import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_2LONG_opcode; 017import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_IFCMP_opcode; 018import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_2INT_opcode; 019import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_2LONG_opcode; 020import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_IFCMP_opcode; 021import static org.jikesrvm.compilers.opt.ir.Operators.LONG_IFCMP_opcode; 022import static org.jikesrvm.compilers.opt.ir.Operators.LONG_MUL_opcode; 023import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SHL_opcode; 024import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SHR_opcode; 025import static org.jikesrvm.compilers.opt.ir.Operators.LONG_USHR_opcode; 026import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_ADD; 027import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_CMP; 028import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_CVTTSD2SI; 029import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_CVTTSS2SI; 030import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_FISTP; 031import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_FLD; 032import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_FLDCW; 033import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_FNSTCW; 034import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_FSTP; 035import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_FUCOMIP; 036import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_IMUL2; 037import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_JCC; 038import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_JCC2; 039import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_JMP; 040import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_MOV; 041import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_MOVSD; 042import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_MOVSS; 043import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_MOVZX__W; 044import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_MOV_opcode; 045import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_MUL; 046import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_NOT; 047import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_OR; 048import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_SAR; 049import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_SHL; 050import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_SHLD; 051import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_SHR; 052import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_SHRD; 053import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_TEST; 054import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_UCOMISD; 055import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_UCOMISS; 056import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IA32_XOR; 057import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IMMQ_MOV; 058import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.IMMQ_MOV_opcode; 059 060import java.util.Enumeration; 061 062import org.jikesrvm.VM; 063import org.jikesrvm.classloader.TypeReference; 064import org.jikesrvm.compilers.opt.DefUse; 065import org.jikesrvm.compilers.opt.OptimizingCompilerException; 066import org.jikesrvm.compilers.opt.ir.BBend; 067import org.jikesrvm.compilers.opt.ir.BasicBlock; 068import org.jikesrvm.compilers.opt.ir.Binary; 069import org.jikesrvm.compilers.opt.ir.IR; 070import org.jikesrvm.compilers.opt.ir.IRTools; 071import org.jikesrvm.compilers.opt.ir.IfCmp; 072import org.jikesrvm.compilers.opt.ir.Instruction; 073import org.jikesrvm.compilers.opt.ir.Label; 074import org.jikesrvm.compilers.opt.ir.Register; 075import org.jikesrvm.compilers.opt.ir.Unary; 076import org.jikesrvm.compilers.opt.ir.ia32.MIR_BinaryAcc; 077import org.jikesrvm.compilers.opt.ir.ia32.MIR_Branch; 078import org.jikesrvm.compilers.opt.ir.ia32.MIR_Compare; 079import org.jikesrvm.compilers.opt.ir.ia32.MIR_CondBranch; 080import org.jikesrvm.compilers.opt.ir.ia32.MIR_CondBranch2; 081import org.jikesrvm.compilers.opt.ir.ia32.MIR_DoubleShift; 082import org.jikesrvm.compilers.opt.ir.ia32.MIR_Move; 083import org.jikesrvm.compilers.opt.ir.ia32.MIR_Multiply; 084import org.jikesrvm.compilers.opt.ir.ia32.MIR_Test; 085import org.jikesrvm.compilers.opt.ir.ia32.MIR_Unary; 086import org.jikesrvm.compilers.opt.ir.ia32.MIR_UnaryAcc; 087import org.jikesrvm.compilers.opt.ir.ia32.MIR_UnaryNoRes; 088import org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet; 089import org.jikesrvm.compilers.opt.ir.operand.BranchOperand; 090import org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand; 091import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand; 092import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand; 093import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; 094import org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand; 095import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand; 096import org.jikesrvm.compilers.opt.ir.operand.Operand; 097import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 098import org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand; 099import org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand; 100import org.jikesrvm.runtime.Entrypoints; 101import org.jikesrvm.util.Bits; 102 103/** 104 * Handles the conversion from LIR to MIR of operators whose 105 * expansion requires the introduction of new control flow (new basic blocks). 106 */ 107public abstract class ComplexLIR2MIRExpansion extends IRTools { 108 109 /** 110 * Converts the given IR to low level IA32 IR. 111 * 112 * @param ir IR to convert 113 */ 114 public static void convert(IR ir) { 115 Instruction nextInstr; 116 for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = nextInstr) { 117 switch (s.getOpcode()) { 118 case FLOAT_IFCMP_opcode: 119 case DOUBLE_IFCMP_opcode: 120 nextInstr = fp_ifcmp(s); 121 break; 122 case FLOAT_2INT_opcode: 123 nextInstr = float_2int(s, ir); 124 break; 125 case FLOAT_2LONG_opcode: 126 nextInstr = float_2long(s, ir); 127 break; 128 case DOUBLE_2INT_opcode: 129 nextInstr = double_2int(s, ir); 130 break; 131 case DOUBLE_2LONG_opcode: 132 nextInstr = double_2long(s, ir); 133 break; 134 135 // long operations. Expand them into other operations 136 // for 32-bit addressing and leave them unchanged for 137 // 64-bit addressing. 138 139 case LONG_MUL_opcode: 140 if (VM.BuildFor32Addr) { 141 nextInstr = long_mul(s, ir); 142 break; 143 } 144 // Fall through 145 case LONG_SHL_opcode: 146 if (VM.BuildFor32Addr) { 147 nextInstr = long_shl(s, ir); 148 break; 149 } 150 // Fall through 151 case LONG_SHR_opcode: 152 if (VM.BuildFor32Addr) { 153 nextInstr = long_shr(s, ir); 154 break; 155 } 156 // Fall through 157 case LONG_USHR_opcode: 158 if (VM.BuildFor32Addr) { 159 nextInstr = long_ushr(s, ir); 160 break; 161 } 162 // Fall through 163 case LONG_IFCMP_opcode: { 164 if (VM.BuildFor32Addr) { 165 Operand val2 = IfCmp.getVal2(s); 166 if (val2 instanceof RegisterOperand) { 167 nextInstr = long_ifcmp(s, ir); 168 } else { 169 nextInstr = long_ifcmp_imm(s, ir); 170 } 171 break; 172 } 173 // Fall through 174 } 175 default: 176 nextInstr = s.nextInstructionInCodeOrder(); 177 break; 178 } 179 } 180 DefUse.recomputeSpansBasicBlock(ir); 181 } 182 183 private static Instruction float_2int(Instruction s, IR ir) { 184 Instruction nextInstr = s.nextInstructionInCodeOrder(); 185 while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) { 186 nextInstr = nextInstr.nextInstructionInCodeOrder(); 187 } 188 // we need 6 basic blocks (in code order) 189 // 1: the current block that does a test to see if this is a regular f2i or 190 // branches to the maxint/NaN case 191 // 2: a block to perform a regular f2i 192 // 3: a block to test for NaN 193 // 4: a block to perform give maxint 194 // 5: a block to perform NaN 195 // 6: the next basic block 196 BasicBlock testBB = s.getBasicBlock(); 197 BasicBlock nextBB = testBB.splitNodeAt(s,ir); 198 ir.cfg.linkInCodeOrder(testBB, nextBB); 199 BasicBlock nanBB = testBB.splitNodeAt(s,ir); 200 ir.cfg.linkInCodeOrder(testBB, nanBB); 201 BasicBlock maxintBB = testBB.splitNodeAt(s,ir); 202 ir.cfg.linkInCodeOrder(testBB, maxintBB); 203 BasicBlock nanTestBB = testBB.splitNodeAt(s,ir); 204 ir.cfg.linkInCodeOrder(testBB, nanTestBB); 205 BasicBlock f2iBB = testBB.splitNodeAt(s,ir); 206 ir.cfg.linkInCodeOrder(testBB, f2iBB); 207 208 // Move the maxintFloat value and the value into registers and compare and 209 // branch if they are <= or unordered. NB we don't use a memory operand as 210 // that would require 2 jccs 211 RegisterOperand result = Unary.getResult(s); 212 RegisterOperand value = Unary.getVal(s).asRegister(); 213 MemoryOperand maxint = BURS_Helpers.loadFromJTOC(Entrypoints.maxintFloatField.getOffset(), (byte)4); 214 RegisterOperand maxintReg = ir.regpool.makeTempFloat(); 215 s.insertBefore(CPOS(s,MIR_Move.create(IA32_MOVSS, maxintReg, maxint))); 216 MIR_Compare.mutate(s, IA32_UCOMISS, maxintReg.copyRO(), value); 217 testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 218 IA32ConditionOperand.LLE(), 219 nanTestBB.makeJumpTarget(), 220 BranchProfileOperand.unlikely()))); 221 testBB.insertOut(f2iBB); 222 testBB.insertOut(nanTestBB); 223 224 // Convert float to int knowing that if the value is < min int the Intel 225 // unspecified result is min int 226 f2iBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_CVTTSS2SI, result, value.copy()))); 227 f2iBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 228 nextBB.makeJumpTarget()))); 229 f2iBB.insertOut(nextBB); 230 231 // Did the compare find a NaN or a maximum integer? 232 nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 233 IA32ConditionOperand.PE(), 234 nanBB.makeJumpTarget(), 235 BranchProfileOperand.unlikely()))); 236 nanTestBB.insertOut(nanBB); 237 nanTestBB.insertOut(maxintBB); 238 239 // Value was >= max integer 240 maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 241 result.copyRO(), 242 IC(Integer.MAX_VALUE)))); 243 maxintBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 244 nextBB.makeJumpTarget()))); 245 maxintBB.insertOut(nextBB); 246 247 // In case of NaN result is 0 248 nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 249 result.copyRO(), 250 IC(0)))); 251 nanBB.insertOut(nextBB); 252 return nextInstr; 253 } 254 255 private static PhysicalRegisterSet phys(IR ir) { 256 return ir.regpool.getPhysicalRegisterSet().asIA32(); 257 } 258 259 private static Instruction float_2long(Instruction s, IR ir) { 260 Instruction nextInstr = s.nextInstructionInCodeOrder(); 261 while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) { 262 nextInstr = nextInstr.nextInstructionInCodeOrder(); 263 } 264 // we need 6 basic blocks (in code order) 265 // 1: the current block that does a test to see if this is a regular f2l or 266 // branches to the maxint/NaN case 267 // 2: a block to perform a regular f2l 268 // 3: a block to test for NaN 269 // 4: a block to perform give maxint 270 // 5: a block to perform NaN 271 // 6: the next basic block 272 BasicBlock testBB = s.getBasicBlock(); 273 BasicBlock nextBB = testBB.splitNodeAt(s,ir); 274 ir.cfg.linkInCodeOrder(testBB, nextBB); 275 BasicBlock nanBB = testBB.splitNodeAt(s,ir); 276 ir.cfg.linkInCodeOrder(testBB, nanBB); 277 BasicBlock maxintBB = testBB.splitNodeAt(s,ir); 278 ir.cfg.linkInCodeOrder(testBB, maxintBB); 279 BasicBlock nanTestBB = testBB.splitNodeAt(s,ir); 280 ir.cfg.linkInCodeOrder(testBB, nanTestBB); 281 BasicBlock f2lBB = testBB.splitNodeAt(s,ir); 282 ir.cfg.linkInCodeOrder(testBB, f2lBB); 283 284 if (VM.BuildFor32Addr) { 285 // Move the maxlongFloat value and the value into x87 registers and compare and 286 // branch if they are <= or unordered. 287 RegisterOperand resultHi = Unary.getResult(s); 288 resultHi.setType(TypeReference.Int); 289 RegisterOperand resultLo = new RegisterOperand(ir.regpool.getSecondReg(resultHi.getRegister()), 290 TypeReference.Int); 291 RegisterOperand value = Unary.getVal(s).asRegister(); 292 RegisterOperand cw = ir.regpool.makeTempInt(); 293 MemoryOperand maxlong = BURS_Helpers.loadFromJTOC(Entrypoints.maxlongFloatField.getOffset(), (byte)4); 294 RegisterOperand st0 = new RegisterOperand(phys(ir).getST0(), 295 TypeReference.Float); 296 RegisterOperand st1 = new RegisterOperand(phys(ir).getST1(), 297 TypeReference.Float); 298 int offset = -ir.stackManager.allocateSpaceForConversion(); 299 StackLocationOperand slLo = new StackLocationOperand(true, offset, 4); 300 StackLocationOperand slHi = new StackLocationOperand(true, offset + 4, 4); 301 StackLocationOperand sl = new StackLocationOperand(true, offset, 8); 302 MemoryOperand scratchLo = new MemoryOperand(ir.regpool.makeTROp(), null, (byte)0, 303 Entrypoints.scratchStorageField.getOffset(), (byte)4, 304 new LocationOperand(Entrypoints.scratchStorageField), null); 305 MemoryOperand scratchHi = new MemoryOperand(ir.regpool.makeTROp(), null, (byte)0, 306 Entrypoints.scratchStorageField.getOffset().plus(4), (byte)4, 307 new LocationOperand(Entrypoints.scratchStorageField), null); 308 309 s.insertBefore(CPOS(s, MIR_Move.create(IA32_MOVSS, slLo, value))); 310 s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0, slLo.copy()))); 311 s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0.copyRO(), maxlong))); 312 MIR_Compare.mutate(s, IA32_FUCOMIP, st0.copyRO(), st1); 313 testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 314 IA32ConditionOperand.LLE(), 315 nanTestBB.makeJumpTarget(), 316 BranchProfileOperand.unlikely()))); 317 testBB.insertOut(f2lBB); 318 testBB.insertOut(nanTestBB); 319 320 // Convert float to long knowing that if the value is < min long the Intel 321 // unspecified result is min long 322 // TODO: this would be a lot simpler and faster with SSE3's FISTTP instruction 323 f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FNSTCW, scratchLo.copy()))); 324 f2lBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_MOVZX__W, cw, scratchLo.copy()))); 325 f2lBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_OR, cw, IC(0xC00)))); 326 f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, scratchHi, cw.copyRO()))); 327 f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchHi.copy()))); 328 f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FISTP, sl, st0.copyRO()))); 329 f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchLo.copy()))); 330 f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo, slLo.copy()))); 331 f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi, slHi))); 332 f2lBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 333 nextBB.makeJumpTarget()))); 334 f2lBB.insertOut(nextBB); 335 336 // Did the compare find a NaN or a maximum integer? 337 nanTestBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FSTP, st0.copyRO(), st0.copyRO()))); 338 nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 339 IA32ConditionOperand.PE(), 340 nanBB.makeJumpTarget(), 341 BranchProfileOperand.unlikely()))); 342 nanTestBB.insertOut(nanBB); 343 nanTestBB.insertOut(maxintBB); 344 345 // Value was >= max long 346 maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 347 resultLo.copyRO(), 348 IC((int)Long.MAX_VALUE)))); 349 maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 350 resultHi.copyRO(), 351 IC((int)(Long.MAX_VALUE >>> 32))))); 352 maxintBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 353 nextBB.makeJumpTarget()))); 354 maxintBB.insertOut(nextBB); 355 356 // In case of NaN result is 0 357 nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 358 resultLo.copyRO(), 359 IC(0)))); 360 nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 361 resultHi.copyRO(), 362 IC(0)))); 363 nanBB.insertOut(nextBB); 364 } else { 365 // Move the maxlongFloat value and the value into x87 registers and compare and 366 // branch if they are <= or unordered. 367 RegisterOperand result = Unary.getResult(s); 368 result.setType(TypeReference.Long); 369 RegisterOperand value = Unary.getVal(s).asRegister(); 370 RegisterOperand cw = ir.regpool.makeTempInt(); 371 MemoryOperand maxlong = BURS_Helpers.loadFromJTOC(Entrypoints.maxlongFloatField.getOffset(), (byte)4); 372 RegisterOperand st0 = new RegisterOperand(phys(ir).getST0(), 373 TypeReference.Float); 374 RegisterOperand st1 = new RegisterOperand(phys(ir).getST1(), 375 TypeReference.Float); 376 int offset = -ir.stackManager.allocateSpaceForConversion(); 377 StackLocationOperand sl = new StackLocationOperand(true, offset, 8); 378 MemoryOperand scratchLo = new MemoryOperand(ir.regpool.makeTROp(), null, (byte)0, 379 Entrypoints.scratchStorageField.getOffset(), (byte)4, 380 new LocationOperand(Entrypoints.scratchStorageField), null); 381 MemoryOperand scratchHi = new MemoryOperand(ir.regpool.makeTROp(), null, (byte)0, 382 Entrypoints.scratchStorageField.getOffset().plus(4), (byte)4, 383 new LocationOperand(Entrypoints.scratchStorageField), null); 384 385 s.insertBefore(CPOS(s, MIR_Move.create(IA32_MOVSS, sl, value))); 386 s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0, sl.copy()))); 387 s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0.copyRO(), maxlong))); 388 MIR_Compare.mutate(s, IA32_FUCOMIP, st0.copyRO(), st1); 389 testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 390 IA32ConditionOperand.LLE(), 391 nanTestBB.makeJumpTarget(), 392 BranchProfileOperand.unlikely()))); 393 testBB.insertOut(f2lBB); 394 testBB.insertOut(nanTestBB); 395 396 // Convert float to long knowing that if the value is < min long the Intel 397 // unspecified result is min long 398 // TODO: this would be a lot simpler and faster with SSE3's FISTTP instruction 399 f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FNSTCW, scratchLo.copy()))); 400 f2lBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_MOVZX__W, cw, scratchLo.copy()))); 401 f2lBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_OR, cw, IC(0xC00)))); 402 f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, scratchHi, cw.copyRO()))); 403 f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchHi.copy()))); 404 f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FISTP, sl, st0.copyRO()))); 405 f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchLo.copy()))); 406 f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, result, sl.copy()))); 407 f2lBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 408 nextBB.makeJumpTarget()))); 409 f2lBB.insertOut(nextBB); 410 411 // Did the compare find a NaN or a maximum integer? 412 nanTestBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FSTP, st0.copyRO(), st0.copyRO()))); 413 nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 414 IA32ConditionOperand.PE(), 415 nanBB.makeJumpTarget(), 416 BranchProfileOperand.unlikely()))); 417 nanTestBB.insertOut(nanBB); 418 nanTestBB.insertOut(maxintBB); 419 420 // Value was >= max long 421 maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 422 result.copyRO(), 423 LC(Long.MAX_VALUE)))); 424 maxintBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 425 nextBB.makeJumpTarget()))); 426 maxintBB.insertOut(nextBB); 427 428 // In case of NaN result is 0 429 nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 430 result.copyRO(), 431 LC(0)))); 432 nanBB.insertOut(nextBB); 433 } 434 return nextInstr; 435 } 436 437 private static Instruction double_2int(Instruction s, IR ir) { 438 Instruction nextInstr = s.nextInstructionInCodeOrder(); 439 while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) { 440 nextInstr = nextInstr.nextInstructionInCodeOrder(); 441 } 442 // we need 6 basic blocks (in code order) 443 // 1: the current block that does a test to see if this is a regular d2i or 444 // branches to the maxint/NaN case 445 // 2: a block to perform a regular d2i 446 // 3: a block to test for NaN 447 // 4: a block to perform give maxint 448 // 5: a block to perform NaN 449 // 6: the next basic block 450 BasicBlock testBB = s.getBasicBlock(); 451 BasicBlock nextBB = testBB.splitNodeAt(s,ir); 452 ir.cfg.linkInCodeOrder(testBB, nextBB); 453 BasicBlock nanBB = testBB.splitNodeAt(s,ir); 454 ir.cfg.linkInCodeOrder(testBB, nanBB); 455 BasicBlock maxintBB = testBB.splitNodeAt(s,ir); 456 ir.cfg.linkInCodeOrder(testBB, maxintBB); 457 BasicBlock nanTestBB = testBB.splitNodeAt(s,ir); 458 ir.cfg.linkInCodeOrder(testBB, nanTestBB); 459 BasicBlock d2iBB = testBB.splitNodeAt(s,ir); 460 ir.cfg.linkInCodeOrder(testBB, d2iBB); 461 462 // Move the maxint value and the value into registers and compare and 463 // branch if they are <= or unordered. NB we don't use a memory operand as 464 // that would require 2 jccs 465 RegisterOperand result = Unary.getResult(s); 466 RegisterOperand value = Unary.getVal(s).asRegister(); 467 MemoryOperand maxint = BURS_Helpers.loadFromJTOC(Entrypoints.maxintField.getOffset(), (byte)8); 468 RegisterOperand maxintReg = ir.regpool.makeTempFloat(); 469 s.insertBefore(CPOS(s,MIR_Move.create(IA32_MOVSD, maxintReg, maxint))); 470 MIR_Compare.mutate(s, IA32_UCOMISD, maxintReg.copyRO(), value); 471 testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 472 IA32ConditionOperand.LLE(), 473 nanTestBB.makeJumpTarget(), 474 BranchProfileOperand.unlikely()))); 475 testBB.insertOut(d2iBB); 476 testBB.insertOut(nanTestBB); 477 478 // Convert float to int knowing that if the value is < min int the Intel 479 // unspecified result is min int 480 d2iBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_CVTTSD2SI, result, value.copy()))); 481 d2iBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 482 nextBB.makeJumpTarget()))); 483 d2iBB.insertOut(nextBB); 484 485 // Did the compare find a NaN or a maximum integer? 486 nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 487 IA32ConditionOperand.PE(), 488 nanBB.makeJumpTarget(), 489 BranchProfileOperand.unlikely()))); 490 nanTestBB.insertOut(nanBB); 491 nanTestBB.insertOut(maxintBB); 492 493 // Value was >= max integer 494 maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 495 result.copyRO(), 496 IC(Integer.MAX_VALUE)))); 497 maxintBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 498 nextBB.makeJumpTarget()))); 499 maxintBB.insertOut(nextBB); 500 501 // In case of NaN result is 0 502 nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 503 result.copyRO(), 504 IC(0)))); 505 nanBB.insertOut(nextBB); 506 return nextInstr; 507 } 508 509 private static Instruction double_2long(Instruction s, IR ir) { 510 Instruction nextInstr = s.nextInstructionInCodeOrder(); 511 while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) { 512 nextInstr = nextInstr.nextInstructionInCodeOrder(); 513 } 514 // we need 6 basic blocks (in code order) 515 // 1: the current block that does a test to see if this is a regular f2l or 516 // branches to the maxint/NaN case 517 // 2: a block to perform a regular f2l 518 // 3: a block to test for NaN 519 // 4: a block to perform give maxint 520 // 5: a block to perform NaN 521 // 6: the next basic block 522 BasicBlock testBB = s.getBasicBlock(); 523 BasicBlock nextBB = testBB.splitNodeAt(s,ir); 524 ir.cfg.linkInCodeOrder(testBB, nextBB); 525 BasicBlock nanBB = testBB.splitNodeAt(s,ir); 526 ir.cfg.linkInCodeOrder(testBB, nanBB); 527 BasicBlock maxintBB = testBB.splitNodeAt(s,ir); 528 ir.cfg.linkInCodeOrder(testBB, maxintBB); 529 BasicBlock nanTestBB = testBB.splitNodeAt(s,ir); 530 ir.cfg.linkInCodeOrder(testBB, nanTestBB); 531 BasicBlock d2lBB = testBB.splitNodeAt(s,ir); 532 ir.cfg.linkInCodeOrder(testBB, d2lBB); 533 534 // Move the maxlongFloat value and the value into x87 registers and compare and 535 // branch if they are <= or unordered. 536 if (VM.BuildFor32Addr) { 537 RegisterOperand resultHi = Unary.getResult(s); 538 resultHi.setType(TypeReference.Int); 539 RegisterOperand resultLo = new RegisterOperand(ir.regpool.getSecondReg(resultHi.getRegister()), 540 TypeReference.Int); 541 RegisterOperand value = Unary.getVal(s).asRegister(); 542 RegisterOperand cw = ir.regpool.makeTempInt(); 543 MemoryOperand maxlong = BURS_Helpers.loadFromJTOC(Entrypoints.maxlongField.getOffset(), (byte)8); 544 RegisterOperand st0 = new RegisterOperand(phys(ir).getST0(), 545 TypeReference.Double); 546 RegisterOperand st1 = new RegisterOperand(phys(ir).getST1(), 547 TypeReference.Double); 548 int offset = -ir.stackManager.allocateSpaceForConversion(); 549 StackLocationOperand slLo = new StackLocationOperand(true, offset, 4); 550 StackLocationOperand slHi = new StackLocationOperand(true, offset + 4, 4); 551 StackLocationOperand sl = new StackLocationOperand(true, offset, 8); 552 MemoryOperand scratchLo = new MemoryOperand(ir.regpool.makeTROp(), null, (byte)0, 553 Entrypoints.scratchStorageField.getOffset(), (byte)4, 554 new LocationOperand(Entrypoints.scratchStorageField), null); 555 MemoryOperand scratchHi = new MemoryOperand(ir.regpool.makeTROp(), null, (byte)0, 556 Entrypoints.scratchStorageField.getOffset().plus(4), (byte)4, 557 new LocationOperand(Entrypoints.scratchStorageField), null); 558 559 s.insertBefore(CPOS(s, MIR_Move.create(IA32_MOVSD, sl, value))); 560 s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0, sl.copy()))); 561 s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0.copyRO(), maxlong))); 562 MIR_Compare.mutate(s, IA32_FUCOMIP, st0.copyRO(), st1); 563 testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 564 IA32ConditionOperand.LLE(), 565 nanTestBB.makeJumpTarget(), 566 BranchProfileOperand.unlikely()))); 567 testBB.insertOut(d2lBB); 568 testBB.insertOut(nanTestBB); 569 570 // Convert double to long knowing that if the value is < min long the Intel 571 // unspecified result is min long 572 // TODO: this would be a lot simpler and faster with SSE3's FISTTP instruction 573 d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FNSTCW, scratchLo.copy()))); 574 d2lBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_MOVZX__W, cw, scratchLo.copy()))); 575 d2lBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_OR, cw, IC(0xC00)))); 576 d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, scratchHi, cw.copyRO()))); 577 d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchHi.copy()))); 578 d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FISTP, sl.copy(), st0.copyRO()))); 579 d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchLo.copy()))); 580 d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo, slLo))); 581 d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi, slHi))); 582 d2lBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 583 nextBB.makeJumpTarget()))); 584 d2lBB.insertOut(nextBB); 585 586 // Did the compare find a NaN or a maximum integer? 587 nanTestBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FSTP, st0.copyRO(), st0.copyRO()))); 588 nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 589 IA32ConditionOperand.PE(), 590 nanBB.makeJumpTarget(), 591 BranchProfileOperand.unlikely()))); 592 nanTestBB.insertOut(nanBB); 593 nanTestBB.insertOut(maxintBB); 594 595 // Value was >= max long 596 maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 597 resultLo.copyRO(), 598 IC((int)Long.MAX_VALUE)))); 599 maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 600 resultHi.copyRO(), 601 IC((int)(Long.MAX_VALUE >>> 32))))); 602 maxintBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 603 nextBB.makeJumpTarget()))); 604 maxintBB.insertOut(nextBB); 605 606 // In case of NaN result is 0 607 nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 608 resultLo.copyRO(), 609 IC(0)))); 610 nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 611 resultHi.copyRO(), 612 IC(0)))); 613 nanBB.insertOut(nextBB); 614 return nextInstr; 615 } else { 616 RegisterOperand result = Unary.getResult(s); 617 RegisterOperand value = Unary.getVal(s).asRegister(); 618 RegisterOperand cw = ir.regpool.makeTempInt(); 619 MemoryOperand maxlong = BURS_Helpers.loadFromJTOC(Entrypoints.maxlongField.getOffset(), (byte)8); 620 RegisterOperand st0 = new RegisterOperand(phys(ir).getST0(), 621 TypeReference.Double); 622 RegisterOperand st1 = new RegisterOperand(phys(ir).getST1(), 623 TypeReference.Double); 624 int offset = -ir.stackManager.allocateSpaceForConversion(); 625 StackLocationOperand sl = new StackLocationOperand(true, offset, 8); 626 MemoryOperand scratchLo = new MemoryOperand(ir.regpool.makeTROp(), null, (byte)0, 627 Entrypoints.scratchStorageField.getOffset(), (byte)4, 628 new LocationOperand(Entrypoints.scratchStorageField), null); 629 MemoryOperand scratchHi = new MemoryOperand(ir.regpool.makeTROp(), null, (byte)0, 630 Entrypoints.scratchStorageField.getOffset().plus(4), (byte)4, 631 new LocationOperand(Entrypoints.scratchStorageField), null); 632 633 s.insertBefore(CPOS(s, MIR_Move.create(IA32_MOVSD, sl, value))); 634 s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0, sl.copy()))); 635 s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0.copyRO(), maxlong))); 636 MIR_Compare.mutate(s, IA32_FUCOMIP, st0.copyRO(), st1); 637 testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 638 IA32ConditionOperand.LLE(), 639 nanTestBB.makeJumpTarget(), 640 BranchProfileOperand.unlikely()))); 641 testBB.insertOut(d2lBB); 642 testBB.insertOut(nanTestBB); 643 644 // Convert double to long knowing that if the value is < min long the Intel 645 // unspecified result is min long 646 // TODO: this would be a lot simpler and faster with SSE3's FISTTP instruction 647 d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FNSTCW, scratchLo.copy()))); 648 d2lBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_MOVZX__W, cw, scratchLo.copy()))); 649 d2lBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_OR, cw, IC(0xC00)))); 650 d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, scratchHi, cw.copyRO()))); 651 d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchHi.copy()))); 652 d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FISTP, sl.copy(), st0.copyRO()))); 653 d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchLo.copy()))); 654 d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, result, sl))); 655 d2lBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 656 nextBB.makeJumpTarget()))); 657 d2lBB.insertOut(nextBB); 658 659 // Did the compare find a NaN or a maximum integer? 660 nanTestBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FSTP, st0.copyRO(), st0.copyRO()))); 661 nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 662 IA32ConditionOperand.PE(), 663 nanBB.makeJumpTarget(), 664 BranchProfileOperand.unlikely()))); 665 nanTestBB.insertOut(nanBB); 666 nanTestBB.insertOut(maxintBB); 667 668 // Value was >= max long 669 maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 670 result.copyRO(), 671 LC((int)Long.MAX_VALUE)))); 672 maxintBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 673 nextBB.makeJumpTarget()))); 674 maxintBB.insertOut(nextBB); 675 676 // In case of NaN result is 0 677 nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 678 result.copyRO(), 679 LC(0)))); 680 nanBB.insertOut(nextBB); 681 return nextInstr; 682 } 683 } 684 685 private static Instruction long_shl(Instruction s, IR ir) { 686 Instruction nextInstr = s.nextInstructionInCodeOrder(); 687 while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) { 688 nextInstr = nextInstr.nextInstructionInCodeOrder(); 689 } 690 // we need 4 basic blocks 691 // 1: the current block that does a test if the shift is > 32 692 // 2: a block to perform a shift in the range 32 to 63 693 // 3: a block to perform a shift in the range 0 to 31 694 // 4: the next basic block 695 BasicBlock testBB = s.getBasicBlock(); 696 BasicBlock nextBB = testBB.splitNodeAt(s,ir); 697 ir.cfg.linkInCodeOrder(testBB, nextBB); 698 BasicBlock shift32BB = testBB.splitNodeAt(s,ir); 699 ir.cfg.linkInCodeOrder(testBB, shift32BB); 700 BasicBlock shift64BB = testBB.splitNodeAt(s,ir); 701 ir.cfg.linkInCodeOrder(testBB, shift64BB); 702 703 // Source registers 704 Register lhsReg = Binary.getResult(s).getRegister(); 705 Register lowlhsReg = ir.regpool.getSecondReg(lhsReg); 706 Operand val1 = Binary.getVal1(s); 707 Register rhsReg; 708 Register lowrhsReg; 709 if (val1.isRegister()) { 710 rhsReg = val1.asRegister().getRegister(); 711 lowrhsReg = ir.regpool.getSecondReg(rhsReg); 712 } else { 713 // shift is of a constant so set up registers 714 int low = val1.asLongConstant().lower32(); 715 int high = val1.asLongConstant().upper32(); 716 717 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 718 new RegisterOperand(lowlhsReg, TypeReference.Int), 719 IC(low)))); 720 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 721 new RegisterOperand(lhsReg, TypeReference.Int), 722 IC(high)))); 723 rhsReg = lhsReg; 724 lowrhsReg = lowlhsReg; 725 } 726 727 // ecx = shift amount 728 Register ecx = phys(ir).getECX(); 729 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 730 new RegisterOperand(ecx, TypeReference.Int), 731 Binary.getVal2(s)))); 732 733 // Determine shift of 32 to 63 or 0 to 31 734 testBB.appendInstruction(CPOS(s, MIR_Test.create(IA32_TEST, 735 new RegisterOperand(ecx, TypeReference.Int), 736 IC(32)))); 737 738 // if (ecx & 32 == 0) goto shift32BB 739 testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 740 IA32ConditionOperand.EQ(), 741 shift32BB.makeJumpTarget(), 742 BranchProfileOperand.likely()))); 743 744 testBB.insertOut(shift32BB); 745 testBB.insertOut(shift64BB); // fall-through 746 747 // Perform shift in the range 32 to 63 748 shift64BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 749 new RegisterOperand(lhsReg, TypeReference.Int), 750 new RegisterOperand(lowrhsReg, TypeReference.Int)))); 751 shift64BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SHL, 752 new RegisterOperand(lhsReg, TypeReference.Int), 753 new RegisterOperand(ecx, TypeReference.Int)))); 754 shift64BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 755 new RegisterOperand(lowlhsReg, TypeReference.Int), 756 IC(0)))); 757 758 shift64BB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 759 nextBB.makeJumpTarget()))); 760 shift64BB.insertOut(nextBB); 761 762 // Perform shift in the range 0 to 31 763 if (lhsReg != rhsReg) { 764 shift32BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 765 new RegisterOperand(lhsReg, TypeReference.Int), 766 new RegisterOperand(rhsReg, TypeReference.Int)))); 767 shift32BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 768 new RegisterOperand(lowlhsReg, TypeReference.Int), 769 new RegisterOperand(lowrhsReg, TypeReference.Int)))); 770 } 771 shift32BB.appendInstruction(CPOS(s, MIR_DoubleShift.create(IA32_SHLD, 772 new RegisterOperand(lhsReg, TypeReference.Int), 773 new RegisterOperand(lowlhsReg, TypeReference.Int), 774 new RegisterOperand(ecx, TypeReference.Int)))); 775 shift32BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SHL, 776 new RegisterOperand(lowlhsReg, TypeReference.Int), 777 new RegisterOperand(ecx, TypeReference.Int)))); 778 779 shift32BB.insertOut(nextBB); 780 781 s.remove(); 782 return nextInstr; 783 } 784 785 private static Instruction long_shr(Instruction s, IR ir) { 786 Instruction nextInstr = s.nextInstructionInCodeOrder(); 787 while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) { 788 nextInstr = nextInstr.nextInstructionInCodeOrder(); 789 } 790 // we need 4 basic blocks 791 // 1: the current block that does a test if the shift is > 32 792 // 2: a block to perform a shift in the range 32 to 63 793 // 3: a block to perform a shift in the range 0 to 31 794 // 4: the next basic block 795 BasicBlock testBB = s.getBasicBlock(); 796 BasicBlock nextBB = testBB.splitNodeAt(s,ir); 797 ir.cfg.linkInCodeOrder(testBB, nextBB); 798 BasicBlock shift32BB = testBB.splitNodeAt(s,ir); 799 ir.cfg.linkInCodeOrder(testBB, shift32BB); 800 BasicBlock shift64BB = testBB.splitNodeAt(s,ir); 801 ir.cfg.linkInCodeOrder(testBB, shift64BB); 802 803 // Source registers 804 Register lhsReg = Binary.getResult(s).getRegister(); 805 Register lowlhsReg = ir.regpool.getSecondReg(lhsReg); 806 Operand val1 = Binary.getVal1(s); 807 Register rhsReg; 808 Register lowrhsReg; 809 if (val1.isRegister()) { 810 rhsReg = val1.asRegister().getRegister(); 811 lowrhsReg = ir.regpool.getSecondReg(rhsReg); 812 } else { 813 // shift is of a constant so set up registers 814 int low = val1.asLongConstant().lower32(); 815 int high = val1.asLongConstant().upper32(); 816 817 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 818 new RegisterOperand(lowlhsReg, TypeReference.Int), 819 IC(low)))); 820 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 821 new RegisterOperand(lhsReg, TypeReference.Int), 822 IC(high)))); 823 rhsReg = lhsReg; 824 lowrhsReg = lowlhsReg; 825 } 826 827 // ecx = shift amount 828 Register ecx = phys(ir).getECX(); 829 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 830 new RegisterOperand(ecx, TypeReference.Int), 831 Binary.getVal2(s)))); 832 833 // Determine shift of 32 to 63 or 0 to 31 834 testBB.appendInstruction(CPOS(s, MIR_Test.create(IA32_TEST, 835 new RegisterOperand(ecx, TypeReference.Int), 836 IC(32)))); 837 838 // if (ecx & 32 == 0) goto shift32BB 839 testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 840 IA32ConditionOperand.EQ(), 841 shift32BB.makeJumpTarget(), 842 BranchProfileOperand.likely()))); 843 844 testBB.insertOut(shift32BB); 845 testBB.insertOut(shift64BB); // fall-through 846 847 // Perform shift in the range 32 to 63 848 shift64BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 849 new RegisterOperand(lowlhsReg, TypeReference.Int), 850 new RegisterOperand(rhsReg, TypeReference.Int)))); 851 if (lhsReg != rhsReg) { 852 shift64BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 853 new RegisterOperand(lhsReg, TypeReference.Int), 854 new RegisterOperand(rhsReg, TypeReference.Int)))); 855 } 856 shift64BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SAR, 857 new RegisterOperand(lowlhsReg, TypeReference.Int), 858 new RegisterOperand(ecx, TypeReference.Int)))); 859 shift64BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SAR, 860 new RegisterOperand(lhsReg, TypeReference.Int), 861 IC(31)))); 862 863 shift64BB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 864 nextBB.makeJumpTarget()))); 865 shift64BB.insertOut(nextBB); 866 867 // Perform shift in the range 0 to 31 868 if (lhsReg != rhsReg) { 869 shift32BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 870 new RegisterOperand(lhsReg, TypeReference.Int), 871 new RegisterOperand(rhsReg, TypeReference.Int)))); 872 shift32BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 873 new RegisterOperand(lowlhsReg, TypeReference.Int), 874 new RegisterOperand(lowrhsReg, TypeReference.Int)))); 875 } 876 shift32BB.appendInstruction(CPOS(s, MIR_DoubleShift.create(IA32_SHRD, 877 new RegisterOperand(lowlhsReg, TypeReference.Int), 878 new RegisterOperand(lhsReg, TypeReference.Int), 879 new RegisterOperand(ecx, TypeReference.Int)))); 880 shift32BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SAR, 881 new RegisterOperand(lhsReg, TypeReference.Int), 882 new RegisterOperand(ecx, TypeReference.Int)))); 883 884 shift32BB.insertOut(nextBB); 885 886 s.remove(); 887 return nextInstr; 888 } 889 890 private static Instruction long_ushr(Instruction s, IR ir) { 891 Instruction nextInstr = s.nextInstructionInCodeOrder(); 892 while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) { 893 nextInstr = nextInstr.nextInstructionInCodeOrder(); 894 } 895 // we need 4 basic blocks 896 // 1: the current block that does a test if the shift is > 32 897 // 2: a block to perform a shift in the range 32 to 63 898 // 3: a block to perform a shift in the range 0 to 31 899 // 4: the next basic block 900 BasicBlock testBB = s.getBasicBlock(); 901 BasicBlock nextBB = testBB.splitNodeAt(s,ir); 902 ir.cfg.linkInCodeOrder(testBB, nextBB); 903 BasicBlock shift32BB = testBB.splitNodeAt(s,ir); 904 ir.cfg.linkInCodeOrder(testBB, shift32BB); 905 BasicBlock shift64BB = testBB.splitNodeAt(s,ir); 906 ir.cfg.linkInCodeOrder(testBB, shift64BB); 907 908 // Source registers 909 Register lhsReg = Binary.getResult(s).getRegister(); 910 Register lowlhsReg = ir.regpool.getSecondReg(lhsReg); 911 Operand val1 = Binary.getVal1(s); 912 Register rhsReg; 913 Register lowrhsReg; 914 if (val1.isRegister()) { 915 rhsReg = val1.asRegister().getRegister(); 916 lowrhsReg = ir.regpool.getSecondReg(rhsReg); 917 } else { 918 // shift is of a constant so set up registers 919 int low = val1.asLongConstant().lower32(); 920 int high = val1.asLongConstant().upper32(); 921 922 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 923 new RegisterOperand(lowlhsReg, TypeReference.Int), 924 IC(low)))); 925 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 926 new RegisterOperand(lhsReg, TypeReference.Int), 927 IC(high)))); 928 rhsReg = lhsReg; 929 lowrhsReg = lowlhsReg; 930 } 931 932 // ecx = shift amount 933 Register ecx = phys(ir).getECX(); 934 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 935 new RegisterOperand(ecx, TypeReference.Int), 936 Binary.getVal2(s)))); 937 938 // Determine shift of 32 to 63 or 0 to 31 939 testBB.appendInstruction(CPOS(s, MIR_Test.create(IA32_TEST, 940 new RegisterOperand(ecx, TypeReference.Int), 941 IC(32)))); 942 943 // if (ecx & 32 == 0) goto shift32BB 944 testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 945 IA32ConditionOperand.EQ(), 946 shift32BB.makeJumpTarget(), 947 BranchProfileOperand.likely()))); 948 949 testBB.insertOut(shift32BB); 950 testBB.insertOut(shift64BB); // fall-through 951 952 // Perform shift in the range 32 to 63 953 shift64BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 954 new RegisterOperand(lowlhsReg, TypeReference.Int), 955 new RegisterOperand(rhsReg, TypeReference.Int)))); 956 shift64BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, 957 new RegisterOperand(lowlhsReg, TypeReference.Int), 958 new RegisterOperand(ecx, TypeReference.Int)))); 959 shift64BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 960 new RegisterOperand(lhsReg, TypeReference.Int), 961 IC(0)))); 962 963 shift64BB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, 964 nextBB.makeJumpTarget()))); 965 shift64BB.insertOut(nextBB); 966 967 // Perform shift in the range 0 to 31 968 if (lhsReg != rhsReg) { 969 shift32BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 970 new RegisterOperand(lhsReg, TypeReference.Int), 971 new RegisterOperand(rhsReg, TypeReference.Int)))); 972 shift32BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 973 new RegisterOperand(lowlhsReg, TypeReference.Int), 974 new RegisterOperand(lowrhsReg, TypeReference.Int)))); 975 } 976 shift32BB.appendInstruction(CPOS(s, MIR_DoubleShift.create(IA32_SHRD, 977 new RegisterOperand(lowlhsReg, TypeReference.Int), 978 new RegisterOperand(lhsReg, TypeReference.Int), 979 new RegisterOperand(ecx, TypeReference.Int)))); 980 shift32BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, 981 new RegisterOperand(lhsReg, TypeReference.Int), 982 new RegisterOperand(ecx, TypeReference.Int)))); 983 984 shift32BB.insertOut(nextBB); 985 986 s.remove(); 987 return nextInstr; 988 } 989 990 private static Instruction long_mul(Instruction s, IR ir) { 991 Instruction nextInstr = s.nextInstructionInCodeOrder(); 992 while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) { 993 nextInstr = nextInstr.nextInstructionInCodeOrder(); 994 } 995 // we need 4 basic blocks 996 // 1: the current block and a test for 32bit or 64bit multiply 997 // 2: 32bit multiply block 998 // 3: 64bit multiply block 999 // 4: the next basic block 1000 BasicBlock testBB = s.getBasicBlock(); 1001 BasicBlock nextBB = testBB.splitNodeAt(s,ir); 1002 ir.cfg.linkInCodeOrder(testBB, nextBB); 1003 BasicBlock mul64BB = testBB.splitNodeAt(s,ir); 1004 ir.cfg.linkInCodeOrder(testBB, mul64BB); 1005 BasicBlock mul32BB = testBB.splitNodeAt(s,ir); 1006 ir.cfg.linkInCodeOrder(testBB, mul32BB); 1007 1008 // Source registers 1009 Register lhsReg = Binary.getResult(s).getRegister(); 1010 Register lowlhsReg = ir.regpool.getSecondReg(lhsReg); 1011 Register rhsReg1 = Binary.getVal1(s).asRegister().getRegister(); 1012 Register lowrhsReg1 = ir.regpool.getSecondReg(rhsReg1); 1013 Register rhsReg2 = Binary.getVal2(s).asRegister().getRegister(); 1014 Register lowrhsReg2 = ir.regpool.getSecondReg(rhsReg2); 1015 1016 // Working registers 1017 Register edx = phys(ir).getEDX(); 1018 Register eax = phys(ir).getEAX(); 1019 Register tmp = ir.regpool.getInteger(); 1020 1021 // The general form of the multiply is 1022 // (a,b) * (c,d) = (l(a imul d)+l(b imul c)+u(b mul d), l(b mul d)) 1023 1024 // Determine whether we need a 32bit or 64bit multiply 1025 // edx, flags = a | c 1026 // edx = d 1027 // eax = b 1028 // if ((a | c) != 0) goto mul64BB 1029 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 1030 new RegisterOperand(edx, TypeReference.Int), 1031 new RegisterOperand(rhsReg2, TypeReference.Int)))); 1032 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 1033 new RegisterOperand(tmp, TypeReference.Int), 1034 new RegisterOperand(rhsReg1, TypeReference.Int)))); 1035 testBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_OR, 1036 new RegisterOperand(edx, TypeReference.Int), 1037 new RegisterOperand(tmp, TypeReference.Int)))); 1038 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 1039 new RegisterOperand(edx, TypeReference.Int), 1040 new RegisterOperand(lowrhsReg1, TypeReference.Int)))); 1041 testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 1042 new RegisterOperand(eax, TypeReference.Int), 1043 new RegisterOperand(lowrhsReg2, TypeReference.Int)))); 1044 testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 1045 IA32ConditionOperand.NE(), 1046 mul64BB.makeJumpTarget(), 1047 BranchProfileOperand.unlikely()))); 1048 testBB.insertOut(mul64BB); 1049 testBB.insertOut(mul32BB); 1050 1051 // multiply 32: on entry EAX = d, EDX = b, tmp = a 1052 // edx:eax = b * d 1053 mul32BB.appendInstruction(CPOS(s, MIR_Multiply.create(IA32_MUL, 1054 new RegisterOperand(edx, TypeReference.Int), 1055 new RegisterOperand(eax, TypeReference.Int), 1056 new RegisterOperand(edx, TypeReference.Int)))); 1057 mul32BB.appendInstruction(MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())); 1058 mul32BB.insertOut(nextBB); 1059 1060 // multiply 64: on entry EAX = d, EDX = b, tmp = a 1061 // edx = b imul c 1062 // tmp = a imul d 1063 // tmp1 = (a imul d) + (b imul c) 1064 // edx:eax = b * d 1065 // edx = u(b mul d) + l(a imul d) + l(b imul c) 1066 mul64BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_IMUL2, 1067 new RegisterOperand(edx, TypeReference.Int), 1068 new RegisterOperand(rhsReg2, TypeReference.Int)))); 1069 mul64BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_IMUL2, 1070 new RegisterOperand(tmp, TypeReference.Int), 1071 new RegisterOperand(eax, TypeReference.Int)))); 1072 mul64BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_ADD, 1073 new RegisterOperand(tmp, TypeReference.Int), 1074 new RegisterOperand(edx, TypeReference.Int)))); 1075 mul64BB.appendInstruction(CPOS(s, MIR_Multiply.create(IA32_MUL, 1076 new RegisterOperand(edx, TypeReference.Int), 1077 new RegisterOperand(eax, TypeReference.Int), 1078 new RegisterOperand(lowrhsReg1, TypeReference.Int)))); 1079 mul64BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_ADD, 1080 new RegisterOperand(edx, TypeReference.Int), 1081 new RegisterOperand(tmp, TypeReference.Int)))); 1082 mul64BB.insertOut(nextBB); 1083 1084 // move result from edx:eax to lhsReg:lowlhsReg 1085 nextBB.prependInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 1086 new RegisterOperand(lhsReg, TypeReference.Int), 1087 new RegisterOperand(edx, TypeReference.Int)))); 1088 nextBB.prependInstruction(CPOS(s, MIR_Move.create(IA32_MOV, 1089 new RegisterOperand(lowlhsReg, TypeReference.Int), 1090 new RegisterOperand(eax, TypeReference.Int)))); 1091 s.remove(); 1092 return nextInstr; 1093 } 1094 1095 private static Instruction long_ifcmp(Instruction s, IR ir) { 1096 Instruction nextInstr = s.nextInstructionInCodeOrder(); 1097 ConditionOperand cond = IfCmp.getCond(s); 1098 Register xh = ((RegisterOperand) IfCmp.getVal1(s)).getRegister(); 1099 Register xl = ir.regpool.getSecondReg(xh); 1100 RegisterOperand yh = (RegisterOperand) IfCmp.getClearVal2(s); 1101 yh.setType(TypeReference.Int); 1102 RegisterOperand yl = new RegisterOperand(ir.regpool.getSecondReg(yh.getRegister()), TypeReference.Int); 1103 basic_long_ifcmp(s, ir, cond, xh, xl, yh, yl); 1104 return nextInstr; 1105 } 1106 1107 private static Instruction long_ifcmp_imm(Instruction s, IR ir) { 1108 Instruction nextInstr = s.nextInstructionInCodeOrder(); 1109 ConditionOperand cond = IfCmp.getCond(s); 1110 Register xh = ((RegisterOperand) IfCmp.getVal1(s)).getRegister(); 1111 Register xl = ir.regpool.getSecondReg(xh); 1112 LongConstantOperand rhs = (LongConstantOperand) IfCmp.getVal2(s); 1113 int low = rhs.lower32(); 1114 int high = rhs.upper32(); 1115 IntConstantOperand yh = IC(high); 1116 IntConstantOperand yl = IC(low); 1117 1118 if (cond.isEQUAL() || cond.isNOT_EQUAL()) { 1119 // tricky... ((xh^yh)|(xl^yl) == 0) <==> (lhll == rhrl)!! 1120 Register th = ir.regpool.getInteger(); 1121 Register tl = ir.regpool.getInteger(); 1122 if (high == 0) { 1123 if (low == 0) { // 0,0 1124 s.insertBefore(MIR_Move.create(IA32_MOV, 1125 new RegisterOperand(th, TypeReference.Int), 1126 new RegisterOperand(xh, TypeReference.Int))); 1127 s.insertBefore(MIR_BinaryAcc.create(IA32_OR, 1128 new RegisterOperand(th, TypeReference.Int), 1129 new RegisterOperand(xl, TypeReference.Int))); 1130 } else if (low == -1) { // 0,-1 1131 s.insertBefore(MIR_Move.create(IA32_MOV, 1132 new RegisterOperand(tl, TypeReference.Int), 1133 new RegisterOperand(xl, TypeReference.Int))); 1134 s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(tl, TypeReference.Int))); 1135 s.insertBefore(MIR_BinaryAcc.create(IA32_OR, 1136 new RegisterOperand(tl, TypeReference.Int), 1137 new RegisterOperand(xh, TypeReference.Int))); 1138 } else { // 0,* 1139 s.insertBefore(MIR_Move.create(IA32_MOV, 1140 new RegisterOperand(tl, TypeReference.Int), 1141 new RegisterOperand(xl, TypeReference.Int))); 1142 s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(tl, TypeReference.Int), yl)); 1143 s.insertBefore(MIR_BinaryAcc.create(IA32_OR, 1144 new RegisterOperand(tl, TypeReference.Int), 1145 new RegisterOperand(xh, TypeReference.Int))); 1146 } 1147 } else if (high == -1) { 1148 if (low == 0) { // -1,0 1149 s.insertBefore(MIR_Move.create(IA32_MOV, 1150 new RegisterOperand(th, TypeReference.Int), 1151 new RegisterOperand(xh, TypeReference.Int))); 1152 s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(th, TypeReference.Int))); 1153 s.insertBefore(MIR_BinaryAcc.create(IA32_OR, 1154 new RegisterOperand(th, TypeReference.Int), 1155 new RegisterOperand(xl, TypeReference.Int))); 1156 } else if (low == -1) { // -1,-1 1157 s.insertBefore(MIR_Move.create(IA32_MOV, 1158 new RegisterOperand(th, TypeReference.Int), 1159 new RegisterOperand(xh, TypeReference.Int))); 1160 s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(th, TypeReference.Int))); 1161 s.insertBefore(MIR_Move.create(IA32_MOV, 1162 new RegisterOperand(tl, TypeReference.Int), 1163 new RegisterOperand(xl, TypeReference.Int))); 1164 s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(tl, TypeReference.Int))); 1165 s.insertBefore(MIR_BinaryAcc.create(IA32_OR, 1166 new RegisterOperand(th, TypeReference.Int), 1167 new RegisterOperand(tl, TypeReference.Int))); 1168 } else { // -1,* 1169 s.insertBefore(MIR_Move.create(IA32_MOV, 1170 new RegisterOperand(th, TypeReference.Int), 1171 new RegisterOperand(xh, TypeReference.Int))); 1172 s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(th, TypeReference.Int))); 1173 s.insertBefore(MIR_Move.create(IA32_MOV, 1174 new RegisterOperand(tl, TypeReference.Int), 1175 new RegisterOperand(xl, TypeReference.Int))); 1176 s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(tl, TypeReference.Int), yl)); 1177 s.insertBefore(MIR_BinaryAcc.create(IA32_OR, 1178 new RegisterOperand(th, TypeReference.Int), 1179 new RegisterOperand(tl, TypeReference.Int))); 1180 } 1181 } else { 1182 if (low == 0) { // *,0 1183 s.insertBefore(MIR_Move.create(IA32_MOV, 1184 new RegisterOperand(th, TypeReference.Int), 1185 new RegisterOperand(xh, TypeReference.Int))); 1186 s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(th, TypeReference.Int), yh)); 1187 s.insertBefore(MIR_BinaryAcc.create(IA32_OR, 1188 new RegisterOperand(th, TypeReference.Int), 1189 new RegisterOperand(xl, TypeReference.Int))); 1190 } else if (low == -1) { // *,-1 1191 s.insertBefore(MIR_Move.create(IA32_MOV, 1192 new RegisterOperand(th, TypeReference.Int), 1193 new RegisterOperand(xh, TypeReference.Int))); 1194 s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(th, TypeReference.Int), yh)); 1195 s.insertBefore(MIR_Move.create(IA32_MOV, 1196 new RegisterOperand(tl, TypeReference.Int), 1197 new RegisterOperand(xl, TypeReference.Int))); 1198 s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(tl, TypeReference.Int))); 1199 s.insertBefore(MIR_BinaryAcc.create(IA32_OR, 1200 new RegisterOperand(th, TypeReference.Int), 1201 new RegisterOperand(tl, TypeReference.Int))); 1202 } else { // neither high nor low is special 1203 s.insertBefore(MIR_Move.create(IA32_MOV, 1204 new RegisterOperand(th, TypeReference.Int), 1205 new RegisterOperand(xh, TypeReference.Int))); 1206 s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(th, TypeReference.Int), yh)); 1207 s.insertBefore(MIR_Move.create(IA32_MOV, 1208 new RegisterOperand(tl, TypeReference.Int), 1209 new RegisterOperand(xl, TypeReference.Int))); 1210 s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(tl, TypeReference.Int), yl)); 1211 s.insertBefore(MIR_BinaryAcc.create(IA32_OR, 1212 new RegisterOperand(th, TypeReference.Int), 1213 new RegisterOperand(tl, TypeReference.Int))); 1214 } 1215 } 1216 MIR_CondBranch.mutate(s, 1217 IA32_JCC, 1218 new IA32ConditionOperand(cond), 1219 IfCmp.getTarget(s), 1220 IfCmp.getBranchProfile(s)); 1221 return nextInstr; 1222 } else { 1223 // pick up a few special cases where the sign of xh is sufficient 1224 if (rhs.value == 0L) { 1225 if (cond.isLESS()) { 1226 // xh < 0 implies true 1227 s.insertBefore(MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), IC(0))); 1228 MIR_CondBranch.mutate(s, 1229 IA32_JCC, 1230 IA32ConditionOperand.LT(), 1231 IfCmp.getTarget(s), 1232 IfCmp.getBranchProfile(s)); 1233 return nextInstr; 1234 } else if (cond.isGREATER_EQUAL()) { 1235 s.insertBefore(MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), IC(0))); 1236 MIR_CondBranch.mutate(s, 1237 IA32_JCC, 1238 IA32ConditionOperand.GE(), 1239 IfCmp.getTarget(s), 1240 IfCmp.getBranchProfile(s)); 1241 return nextInstr; 1242 } 1243 } else if (rhs.value == -1L) { 1244 if (cond.isLESS_EQUAL()) { 1245 s.insertBefore(MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), IC(-1))); 1246 MIR_CondBranch.mutate(s, 1247 IA32_JCC, 1248 IA32ConditionOperand.LE(), 1249 IfCmp.getTarget(s), 1250 IfCmp.getBranchProfile(s)); 1251 return nextInstr; 1252 } else if (cond.isGREATER()) { 1253 s.insertBefore(MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), IC(0))); 1254 MIR_CondBranch.mutate(s, 1255 IA32_JCC, 1256 IA32ConditionOperand.GE(), 1257 IfCmp.getTarget(s), 1258 IfCmp.getBranchProfile(s)); 1259 return nextInstr; 1260 } 1261 } 1262 1263 basic_long_ifcmp(s, ir, cond, xh, xl, yh, yl); 1264 return nextInstr; 1265 } 1266 } 1267 1268 private static void basic_long_ifcmp(Instruction s, IR ir, ConditionOperand cond, Register xh, 1269 Register xl, Operand yh, Operand yl) { 1270 if (cond.isEQUAL() || cond.isNOT_EQUAL()) { 1271 RegisterOperand th = ir.regpool.makeTempInt(); 1272 RegisterOperand tl = ir.regpool.makeTempInt(); 1273 // tricky... ((xh^yh)|(xl^yl) == 0) <==> (lhll == rhrl)!! 1274 s.insertBefore(MIR_Move.create(IA32_MOV, th, new RegisterOperand(xh, TypeReference.Int))); 1275 s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, th.copyD2D(), yh)); 1276 s.insertBefore(MIR_Move.create(IA32_MOV, tl, new RegisterOperand(xl, TypeReference.Int))); 1277 s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, tl.copyD2D(), yl)); 1278 s.insertBefore(MIR_BinaryAcc.create(IA32_OR, th.copyD2D(), tl.copyD2U())); 1279 MIR_CondBranch.mutate(s, 1280 IA32_JCC, 1281 new IA32ConditionOperand(cond), 1282 IfCmp.getTarget(s), 1283 IfCmp.getBranchProfile(s)); 1284 } else { 1285 // Do the naive thing and generate multiple compare/branch implementation. 1286 IA32ConditionOperand cond1; 1287 IA32ConditionOperand cond2; 1288 IA32ConditionOperand cond3; 1289 if (cond.isLESS()) { 1290 cond1 = IA32ConditionOperand.LT(); 1291 cond2 = IA32ConditionOperand.GT(); 1292 cond3 = IA32ConditionOperand.LLT(); 1293 } else if (cond.isGREATER()) { 1294 cond1 = IA32ConditionOperand.GT(); 1295 cond2 = IA32ConditionOperand.LT(); 1296 cond3 = IA32ConditionOperand.LGT(); 1297 } else if (cond.isLESS_EQUAL()) { 1298 cond1 = IA32ConditionOperand.LT(); 1299 cond2 = IA32ConditionOperand.GT(); 1300 cond3 = IA32ConditionOperand.LLE(); 1301 } else if (cond.isGREATER_EQUAL()) { 1302 cond1 = IA32ConditionOperand.GT(); 1303 cond2 = IA32ConditionOperand.LT(); 1304 cond3 = IA32ConditionOperand.LGE(); 1305 } else { 1306 // I don't think we use the unsigned compares for longs, 1307 // so defer actually implementing them until we find a test case. --dave 1308 cond1 = cond2 = cond3 = null; 1309 OptimizingCompilerException.TODO(); 1310 } 1311 1312 BasicBlock myBlock = s.getBasicBlock(); 1313 BasicBlock test2Block = myBlock.createSubBlock(s.bcIndex, ir, 0.25f); 1314 BasicBlock falseBlock = myBlock.splitNodeAt(s, ir); 1315 BasicBlock trueBlock = IfCmp.getTarget(s).target.getBasicBlock(); 1316 1317 falseBlock.recomputeNormalOut(ir); 1318 myBlock.insertOut(test2Block); 1319 myBlock.insertOut(falseBlock); 1320 myBlock.insertOut(trueBlock); 1321 test2Block.insertOut(falseBlock); 1322 test2Block.insertOut(trueBlock); 1323 ir.cfg.linkInCodeOrder(myBlock, test2Block); 1324 ir.cfg.linkInCodeOrder(test2Block, falseBlock); 1325 1326 s.remove(); 1327 1328 myBlock.appendInstruction(CPOS(s, MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), yh))); 1329 myBlock.appendInstruction(CPOS(s, MIR_CondBranch2.create(IA32_JCC2, 1330 cond1, 1331 trueBlock.makeJumpTarget(), 1332 new BranchProfileOperand(), 1333 cond2, 1334 falseBlock.makeJumpTarget(), 1335 new BranchProfileOperand()))); 1336 test2Block.appendInstruction(CPOS(s, MIR_Compare.create(IA32_CMP, new RegisterOperand(xl, TypeReference.Int), yl))); 1337 test2Block.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, 1338 cond3, 1339 trueBlock.makeJumpTarget(), 1340 new BranchProfileOperand()))); 1341 } 1342 } 1343 1344 // the fcmoi/fcmoip was generated by burs 1345 // we do the rest of the expansion here because in some 1346 // cases we must remove a trailing goto, and we 1347 // can't do that in burs! 1348 private static Instruction fp_ifcmp(Instruction s) { 1349 Instruction nextInstr = s.nextInstructionInCodeOrder(); 1350 BranchOperand testFailed; 1351 BasicBlock bb = s.getBasicBlock(); 1352 Instruction lastInstr = bb.lastRealInstruction(); 1353 if (lastInstr.operator() == IA32_JMP) { 1354 // We're in trouble if there is another instruction between s and lastInstr! 1355 if (VM.VerifyAssertions) VM._assert(s.nextInstructionInCodeOrder() == lastInstr); 1356 // Set testFailed to target of GOTO 1357 testFailed = MIR_Branch.getTarget(lastInstr); 1358 nextInstr = lastInstr.nextInstructionInCodeOrder(); 1359 lastInstr.remove(); 1360 } else { 1361 // Set testFailed to label of next (fallthrough basic block) 1362 testFailed = bb.nextBasicBlockInCodeOrder().makeJumpTarget(); 1363 } 1364 1365 // Translate condition operand respecting IA32 FCOMI/COMISS/COMISD 1366 Instruction fcomi = s.prevInstructionInCodeOrder(); 1367 Operand val1 = MIR_Compare.getVal1(fcomi); 1368 Operand val2 = MIR_Compare.getVal2(fcomi); 1369 ConditionOperand c = IfCmp.getCond(s); 1370 BranchOperand target = IfCmp.getTarget(s); 1371 BranchProfileOperand branchProfile = IfCmp.getBranchProfile(s); 1372 1373 // FCOMI sets ZF, PF, and CF as follows: 1374 // Compare Results ZF PF CF 1375 // left > right 0 0 0 1376 // left < right 0 0 1 1377 // left == right 1 0 0 1378 // UNORDERED 1 1 1 1379 1380 // Propagate branch probabilities as follows: assume the 1381 // probability of unordered (first condition) is zero, and 1382 // propagate the original probability to the second condition. 1383 switch (c.value) { 1384 // Branches that WON'T be taken after unordered comparison 1385 // (i.e. UNORDERED is a goto to testFailed) 1386 case ConditionOperand.CMPL_EQUAL: 1387 if (VM.VerifyAssertions) VM._assert(!c.branchIfUnordered()); 1388 // Check whether val1 and val2 operands are the same 1389 if (!val1.similar(val2)) { 1390 s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, 1391 IA32ConditionOperand.PE(), 1392 // PF == 1 1393 testFailed, 1394 new BranchProfileOperand(0f), 1395 IA32ConditionOperand.EQ(), 1396 // ZF == 1 1397 target, 1398 branchProfile)); 1399 s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (testFailed.copy()))); 1400 } else { 1401 // As val1 == val2 result of compare must be == or UNORDERED 1402 s.insertBefore(MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.PO(), // PF == 0 1403 target, branchProfile)); 1404 s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed)); 1405 } 1406 break; 1407 case ConditionOperand.CMPL_GREATER: 1408 if (VM.VerifyAssertions) VM._assert(!c.branchIfUnordered()); 1409 s.insertBefore(MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.LGT(), // CF == 0 and ZF == 0 1410 target, branchProfile)); 1411 s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed)); 1412 break; 1413 case ConditionOperand.CMPG_LESS: 1414 if (VM.VerifyAssertions) VM._assert(!c.branchIfUnordered()); 1415 s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, 1416 IA32ConditionOperand.PE(), 1417 // PF == 1 1418 testFailed, 1419 new BranchProfileOperand(0f), 1420 IA32ConditionOperand.LLT(), 1421 // CF == 1 1422 target, 1423 branchProfile)); 1424 s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (testFailed.copy()))); 1425 break; 1426 case ConditionOperand.CMPL_GREATER_EQUAL: 1427 if (VM.VerifyAssertions) VM._assert(!c.branchIfUnordered()); 1428 s.insertBefore(MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.LGE(), // CF == 0 1429 target, branchProfile)); 1430 s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed)); 1431 break; 1432 case ConditionOperand.CMPG_LESS_EQUAL: 1433 s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, 1434 IA32ConditionOperand.PE(), 1435 // PF == 1 1436 testFailed, 1437 new BranchProfileOperand(0f), 1438 IA32ConditionOperand.LGT(), 1439 // ZF == 0 and CF == 0 1440 (BranchOperand) (testFailed.copy()), 1441 branchProfile)); 1442 s.insertBefore(MIR_Branch.create(IA32_JMP, target)); 1443 break; 1444 // Branches that WILL be taken after unordered comparison 1445 // (i.e. UNORDERED is a goto to target) 1446 case ConditionOperand.CMPL_NOT_EQUAL: 1447 if (VM.VerifyAssertions) VM._assert(c.branchIfUnordered()); 1448 // Check whether val1 and val2 operands are the same 1449 if (!val1.similar(val2)) { 1450 s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, 1451 IA32ConditionOperand.PE(), 1452 // PF == 1 1453 target, 1454 new BranchProfileOperand(0f), 1455 IA32ConditionOperand.NE(), 1456 // ZF == 0 1457 (BranchOperand) (target.copy()), 1458 branchProfile)); 1459 s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed)); 1460 } else { 1461 // As val1 == val2 result of compare must be == or UNORDERED 1462 s.insertBefore(MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.PE(), // PF == 1 1463 target, branchProfile)); 1464 s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed)); 1465 } 1466 break; 1467 case ConditionOperand.CMPL_LESS: 1468 if (VM.VerifyAssertions) VM._assert(c.branchIfUnordered()); 1469 s.insertBefore(MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.LLT(), // CF == 1 1470 target, branchProfile)); 1471 s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed)); 1472 break; 1473 case ConditionOperand.CMPG_GREATER_EQUAL: 1474 if (VM.VerifyAssertions) VM._assert(c.branchIfUnordered()); 1475 s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, 1476 IA32ConditionOperand.PE(), 1477 // PF == 1 1478 target, 1479 new BranchProfileOperand(0f), 1480 IA32ConditionOperand.LLT(), 1481 // CF == 1 1482 testFailed, 1483 branchProfile)); 1484 s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (target.copy()))); 1485 break; 1486 case ConditionOperand.CMPG_GREATER: 1487 if (VM.VerifyAssertions) VM._assert(c.branchIfUnordered()); 1488 s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, 1489 IA32ConditionOperand.PE(), 1490 // PF == 1 1491 target, 1492 new BranchProfileOperand(0f), 1493 IA32ConditionOperand.LGT(), 1494 // ZF == 0 and CF == 0 1495 (BranchOperand) (target.copy()), 1496 branchProfile)); 1497 s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed)); 1498 break; 1499 case ConditionOperand.CMPL_LESS_EQUAL: 1500 if (VM.VerifyAssertions) VM._assert(c.branchIfUnordered()); 1501 s.insertBefore(MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.LLE(), // CF == 1 or ZF == 1 1502 target, branchProfile)); 1503 s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed)); 1504 break; 1505 default: 1506 OptimizingCompilerException.UNREACHABLE(); 1507 } 1508 s.remove(); 1509 return nextInstr; 1510 } 1511 1512 public static void process64BitImmediateValues(IR ir) { 1513 for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; 1514 s = s.nextInstructionInCodeOrder()) { 1515 char opcode = s.getOpcode(); 1516 if (opcode != IMMQ_MOV_opcode) { 1517 if (MIR_Move.conforms(s)) { 1518 Operand moveResult = MIR_Move.getResult(s); 1519 if (opcode == IA32_MOV_opcode && moveResult.isRegister()) { 1520 Operand value = MIR_Move.getValue(s); 1521 if (value.isLongConstant()) { 1522 LongConstantOperand lc = (LongConstantOperand)value; 1523 if (!Bits.fits(lc.value, 32)) { 1524 MIR_Move.mutate(s, IMMQ_MOV, moveResult, value); 1525 continue; 1526 } 1527 } 1528 } 1529 } 1530 for (Enumeration<Operand> ops = s.getOperands(); ops.hasMoreElements();) { 1531 Operand op = ops.nextElement(); 1532 if (op.isLongConstant()) { 1533 LongConstantOperand lc = (LongConstantOperand)op; 1534 if (!Bits.fits(lc.value, 32)) { 1535 RegisterOperand temp = ir.regpool.makeTempLong(); 1536 if (lc.convertedFromRef()) { 1537 temp.flagAsConvertedFromRef(); 1538 } 1539 s.insertBefore(MIR_Move.create(IMMQ_MOV, temp, lc)); 1540 s.replaceOperand(lc, temp.copyD2U()); 1541 } 1542 } 1543 } 1544 } 1545 } 1546 } 1547 1548}