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