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