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