001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Common Public License (CPL);
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/cpl1.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.mir2mc.ia32;
014    
015    import java.util.ArrayList;
016    import static org.jikesrvm.ia32.ArchConstants.SSE2_FULL;
017    import org.jikesrvm.ArchitectureSpecificOpt.AssemblerOpt;
018    import org.jikesrvm.ArchitectureSpecific.Assembler;
019    import org.jikesrvm.VM;
020    import org.jikesrvm.Constants;
021    import org.jikesrvm.compilers.common.assembler.ForwardReference;
022    import org.jikesrvm.compilers.opt.OptimizingCompilerException;
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_Call;
026    import org.jikesrvm.compilers.opt.ir.MIR_Compare;
027    import org.jikesrvm.compilers.opt.ir.MIR_CondBranch;
028    import org.jikesrvm.compilers.opt.ir.MIR_Lea;
029    import org.jikesrvm.compilers.opt.ir.MIR_LowTableSwitch;
030    import org.jikesrvm.compilers.opt.ir.MIR_Move;
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_UnaryNoRes;
034    import org.jikesrvm.compilers.opt.ir.IR;
035    import org.jikesrvm.compilers.opt.ir.Instruction;
036    import org.jikesrvm.compilers.opt.ir.OperandEnumeration;
037    import org.jikesrvm.compilers.opt.ir.Operator;
038    import org.jikesrvm.compilers.opt.ir.Operators;
039    import org.jikesrvm.compilers.opt.ir.Register;
040    import org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet;
041    import org.jikesrvm.compilers.opt.ir.operand.BranchOperand;
042    import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand;
043    import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand;
044    import org.jikesrvm.compilers.opt.ir.operand.Operand;
045    import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
046    import org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand;
047    import org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand;
048    import org.jikesrvm.compilers.opt.regalloc.ia32.PhysicalRegisterConstants;
049    import org.jikesrvm.ia32.TrapConstants;
050    import org.vmmagic.pragma.NoInline;
051    import org.vmmagic.unboxed.Offset;
052    
053    /**
054     *  This class provides support functionality used by the generated
055     * Assembler; it handles basic impedance-matching functionality
056     * such as determining which addressing mode is suitable for a given
057     * IA32MemoryOperand.  This class also provides some boilerplate
058     * methods that do not depend on how instructions sould actually be
059     * assembled, like the top-level generateCode driver.  This class is
060     * not meant to be used in isolation, but rather to provide support
061     * from the Assembler.
062     */
063    abstract class AssemblerBase extends Assembler
064        implements Operators, Constants, PhysicalRegisterConstants {
065    
066      private static final boolean DEBUG_ESTIMATE = false;
067    
068      /**
069       * Hold EBP register object for use in estimating size of memory operands.
070       */
071      private final Register EBP;
072    
073      /**
074       * Hold EBP register object for use in estimating size of memory operands.
075       */
076      private final Register ESP;
077    
078      /**
079       * Operators with byte arguments
080       */
081      private static final Operator[] byteSizeOperators;
082    
083      /**
084       * Operators with word arguments
085       */
086      private static final Operator[] wordSizeOperators;
087    
088      /**
089       * Operators with quad arguments
090       */
091      private static final Operator[] quadSizeOperators;
092    
093      static {
094        ArrayList<Operator> temp = new ArrayList<Operator>();
095        for (Operator opr : Operator.OperatorArray) {
096          if (opr != null && opr.toString().indexOf("__b") != -1) {
097            temp.add(opr);
098          }
099        }
100        byteSizeOperators = temp.toArray(new Operator[temp.size()]);
101        temp.clear();
102        for (Operator opr : Operator.OperatorArray) {
103          if (opr != null && opr.toString().indexOf("__w") != -1) {
104            temp.add(opr);
105          }
106        }
107        wordSizeOperators = temp.toArray(new Operator[temp.size()]);
108        for (Operator opr : Operator.OperatorArray) {
109          if (opr != null && opr.toString().indexOf("__q") != -1) {
110            temp.add(opr);
111          }
112        }
113        quadSizeOperators = temp.toArray(new Operator[temp.size()]);
114      }
115    
116      /**
117       * Construct Assembler object
118       * @see Assembler
119       */
120      AssemblerBase(int bytecodeSize, boolean shouldPrint, IR ir) {
121        super(bytecodeSize, shouldPrint);
122        EBP = ir.regpool.getPhysicalRegisterSet().getEBP();
123        ESP = ir.regpool.getPhysicalRegisterSet().getESP();
124      }
125    
126      /**
127       * Should code created by this assembler instance be allocated in the
128       * hot code code space? The default answer for opt compiled code is yes
129       * (otherwise why are we opt compiling it?).
130       */
131      protected boolean isHotCode() { return true; }
132    
133      /**
134       *  Is the given operand an immediate?  In the IA32 assembly, one
135       * cannot specify floating-point constants, so the possible
136       * immediates we may see are IntegerConstants and
137       * TrapConstants (a trap constant really is an integer), and
138       * jump targets for which the exact offset is known.
139       *
140       * @see #getImm
141       *
142       * @param op the operand being queried
143       * @return true if op represents an immediate
144       */
145      boolean isImm(Operand op) {
146        return (op instanceof IntConstantOperand) ||
147               (op instanceof TrapCodeOperand) ||
148               (op instanceof BranchOperand && op.asBranch().target.getmcOffset() >= 0);
149      }
150    
151      /**
152       *  Return the IA32 ISA encoding of the immediate value
153       * represented by the the given operand.  This method assumes the
154       * operand is an immediate and will likely throw a
155       * ClassCastException if this not the case.  It treats
156       * BranchOperands somewhat differently than isImm does: in
157       * case a branch target is not resolved, it simply returns a wrong
158       * answer and trusts the caller to ignore it. This behavior
159       * simplifies life when generating code for ImmOrLabel operands.
160       *
161       * @see #isImm
162       *
163       * @param op the operand being queried
164       * @return the immediate value represented by the operand
165       */
166      int getImm(Operand op) {
167        if (op.isIntConstant()) {
168          return op.asIntConstant().value;
169        } else if (op.isBranch()) {
170          // used by ImmOrLabel stuff
171          return op.asBranch().target.getmcOffset();
172        } else {
173          return ((TrapCodeOperand) op).getTrapCode() + TrapConstants.RVM_TRAP_BASE;
174        }
175      }
176    
177      /**
178       *  Is the given operand a register operand?
179       *
180       * @see #getReg
181       *
182       * @param op the operand being queried
183       * @return true if op is an RegisterOperand
184       */
185      boolean isReg(Operand op) {
186        return op.isRegister();
187      }
188    
189      boolean isGPR_Reg(Operand op) {
190        return isReg(op);
191      }
192    
193      boolean isFPR_Reg(Operand op) {
194        return isReg(op);
195      }
196    
197      boolean isMM_Reg(Operand op) {
198        return false; // MM registers not currently supported in the OPT compiler
199      }
200    
201      boolean isXMM_Reg(Operand op) {
202        return op.isRegister() && (op.isFloat() || op.isDouble());
203      }
204    
205      /**
206       * Return the machine-level register number corresponding to a given integer
207       * Register. The optimizing compiler has its own notion of register
208       * numbers, which is not the same as the numbers used by the IA32 ISA. This
209       * method takes an optimizing compiler register and translates it into the
210       * appropriate machine-level encoding. This method is not applied directly to
211       * operands, but rather to register objects.
212       *
213       * @see #getBase
214       * @see #getIndex
215       *
216       * @param reg the register being queried
217       * @return the 3 bit machine-level encoding of reg
218       */
219      private GPR getGPMachineRegister(Register reg) {
220        if (VM.VerifyAssertions) {
221          VM._assert(PhysicalRegisterSet.getPhysicalRegisterType(reg) == INT_REG);
222        }
223        return GPR.lookup(reg.number - FIRST_INT);
224      }
225    
226      /**
227       * Return the machine-level register number corresponding to a
228       * given Register.  The optimizing compiler has its own notion
229       * of register numbers, which is not the same as the numbers used
230       * by the IA32 ISA.  This method takes an optimizing compiler
231       * register and translates it into the appropriate machine-level
232       * encoding.  This method is not applied directly to operands, but
233       * rather to register objects.
234       *
235       * @see #getReg
236       * @see #getBase
237       * @see #getIndex
238       *
239       * @param reg the register being queried
240       * @return the 3 bit machine-level encoding of reg
241       */
242      private MachineRegister getMachineRegister(Register reg) {
243        int type = PhysicalRegisterSet.getPhysicalRegisterType(reg);
244        MachineRegister result;
245        if (type == INT_REG) {
246          result = GPR.lookup(reg.number - FIRST_INT);
247        } else {
248          if (VM.VerifyAssertions) VM._assert(type == DOUBLE_REG);
249          if (SSE2_FULL) {
250            if (reg.number < FIRST_SPECIAL) {
251              result = XMM.lookup(reg.number - FIRST_DOUBLE);
252            } else if (reg.number == ST0) {
253              result = FP0;
254            } else {
255              if (VM.VerifyAssertions) VM._assert(reg.number == ST1);
256              result = FP1;
257            }
258          } else {
259            result = FPR.lookup(reg.number - FIRST_DOUBLE);
260          }
261        }
262        return result;
263      }
264    
265      /**
266       * Given a register operand, return the 3 bit IA32 ISA encoding
267       * of that register.  This function translates an optimizing
268       * compiler register operand into the 3 bit IA32 ISA encoding that
269       * can be passed to the Assembler.  This function assumes its
270       * operand is a register operand, and will blow up if it is not;
271       * use isReg to check operands passed to this method.
272       *
273       * @see #isReg
274       *
275       * @param op the register operand being queried
276       * @return the 3 bit IA32 ISA encoding of op
277       */
278      MachineRegister getReg(Operand op) {
279        return getMachineRegister(op.asRegister().getRegister());
280      }
281    
282      GPR getGPR_Reg(Operand op) {
283        return getGPMachineRegister(op.asRegister().getRegister());
284      }
285    
286      FPR getFPR_Reg(Operand op) {
287        return (FPR)getMachineRegister(op.asRegister().getRegister());
288      }
289    
290      MM getMM_Reg(Operand op) {
291        VM._assert(false, "MM registers not currently supported in the opt compiler");
292        return null;
293      }
294    
295      XMM getXMM_Reg(Operand op) {
296        return (XMM)getMachineRegister(op.asRegister().getRegister());
297      }
298    
299      /**
300       * Given a memory operand, return the 3 bit IA32 ISA encoding
301       * of its base regsiter.  This function translates the optimizing
302       * compiler register operand representing the base of the given
303       * memory operand into the 3 bit IA32 ISA encoding that
304       * can be passed to the Assembler.  This function assumes its
305       * operand is a memory operand, and will blow up if it is not;
306       * one should confirm an operand really has a base register before
307       * invoking this method on it.
308       *
309       * @see #isRegDisp
310       * @see #isRegIdx
311       * @see #isRegInd
312       *
313       * @param op the register operand being queried
314       * @return the 3 bit IA32 ISA encoding of the base register of op
315       */
316      GPR getBase(Operand op) {
317        return getGPMachineRegister(((MemoryOperand) op).base.getRegister());
318      }
319    
320      /**
321       * Given a memory operand, return the 3 bit IA32 ISA encoding
322       * of its index regsiter.  This function translates the optimizing
323       * compiler register operand representing the index of the given
324       * memory operand into the 3 bit IA32 ISA encoding that
325       * can be passed to the Assembler.  This function assumes its
326       * operand is a memory operand, and will blow up if it is not;
327       * one should confirm an operand really has an index register before
328       * invoking this method on it.
329       *
330       * @see #isRegIdx
331       * @see #isRegOff
332       *
333       * @param op the register operand being queried
334       * @return the 3 bit IA32 ISA encoding of the index register of op
335       */
336      GPR getIndex(Operand op) {
337        return getGPMachineRegister(((MemoryOperand) op).index.getRegister());
338      }
339    
340      /**
341       *  Given a memory operand, return the 2 bit IA32 ISA encoding
342       * of its scale, suitable for passing to the Assembler to mask
343       * into a SIB byte.  This function assumes its operand is a memory
344       * operand, and will blow up if it is not; one should confirm an
345       * operand really has a scale before invoking this method on it.
346       *
347       * @see #isRegIdx
348       * @see #isRegOff
349       *
350       * @param op the register operand being queried
351       * @return the IA32 ISA encoding of the scale of op
352       */
353      short getScale(Operand op) {
354        return ((MemoryOperand) op).scale;
355      }
356    
357      /**
358       *  Given a memory operand, return the 2 bit IA32 ISA encoding
359       * of its scale, suitable for passing to the Assembler to mask
360       * into a SIB byte.  This function assumes its operand is a memory
361       * operand, and will blow up if it is not; one should confirm an
362       * operand really has a scale before invoking this method on it.
363       *
364       * @see #isRegIdx
365       * @see #isRegOff
366       *
367       * @param op the register operand being queried
368       * @return the IA32 ISA encoding of the scale of op
369       */
370      Offset getDisp(Operand op) {
371        return ((MemoryOperand) op).disp;
372      }
373    
374      /**
375       *  Determine if a given operand is a memory operand representing
376       * register-displacement mode addressing.  This method takes an
377       * arbitrary operand, checks whether it is a memory operand, and,
378       * if it is, checks whether it should be assembled as IA32
379       * register-displacement mode.  That is, does it have a non-zero
380       * displacement and a base register, but no scale and no index
381       * register?
382       *
383       * @param op the operand being queried
384       * @return true if op should be assembled as register-displacement mode
385       */
386      boolean isRegDisp(Operand op) {
387        if (op instanceof MemoryOperand) {
388          MemoryOperand mop = (MemoryOperand) op;
389          return (mop.base != null) && (mop.index == null) && (!mop.disp.isZero()) && (mop.scale == 0);
390        } else {
391          return false;
392        }
393      }
394    
395      /**
396       * Determine if a given operand is a memory operand representing
397       * absolute mode addressing.  This method takes an
398       * arbitrary operand, checks whether it is a memory operand, and,
399       * if it is, checks whether it should be assembled as IA32
400       * absolute address mode.  That is, does it have a non-zero
401       * displacement, but no scale, no scale and no index register?
402       *
403       * @param op the operand being queried
404       * @return true if op should be assembled as absolute mode
405       */
406      boolean isAbs(Operand op) {
407        if (op instanceof MemoryOperand) {
408          MemoryOperand mop = (MemoryOperand) op;
409          return (mop.base == null) && (mop.index == null) && (!mop.disp.isZero()) && (mop.scale == 0);
410        } else {
411          return false;
412        }
413      }
414    
415      /**
416       *  Determine if a given operand is a memory operand representing
417       * register-indirect mode addressing.  This method takes an
418       * arbitrary operand, checks whether it is a memory operand, and,
419       * if it is, checks whether it should be assembled as IA32
420       * register-displacement mode.  That is, does it have a base
421       * register, but no displacement, no scale and no index
422       * register?
423       *
424       * @param op the operand being queried
425       * @return true if op should be assembled as register-indirect mode
426       */
427      boolean isRegInd(Operand op) {
428        if (op instanceof MemoryOperand) {
429          MemoryOperand mop = (MemoryOperand) op;
430          return (mop.base != null) && (mop.index == null) && (mop.disp.isZero()) && (mop.scale == 0);
431        } else {
432          return false;
433        }
434      }
435    
436      /**
437       * Determine if a given operand is a memory operand representing
438       * register-offset mode addressing.  This method takes an
439       * arbitrary operand, checks whether it is a memory operand, and,
440       * if it is, checks whether it should be assembled as IA32
441       * register-offset mode.  That is, does it have a non-zero
442       * displacement, a scale parameter and an index register, but no
443       * base register?
444       *
445       * @param op the operand being queried
446       * @return true if op should be assembled as register-offset mode
447       */
448      boolean isRegOff(Operand op) {
449        if (op instanceof MemoryOperand) {
450          MemoryOperand mop = (MemoryOperand) op;
451          return (mop.base == null) && (mop.index != null);
452        } else {
453          return false;
454        }
455      }
456    
457      /**
458       *  Determine if a given operand is a memory operand representing
459       * the full glory of scaled-index-base addressing.  This method takes an
460       * arbitrary operand, checks whether it is a memory operand, and,
461       * if it is, checks whether it should be assembled as IA32
462       * SIB mode.  That is, does it have a non-zero
463       * displacement, a scale parameter, a base register and an index
464       * register?
465       *
466       * @param op the operand being queried
467       * @return true if op should be assembled as SIB mode
468       */
469      boolean isRegIdx(Operand op) {
470        if (op instanceof MemoryOperand) {
471          return !(isAbs(op) || isRegInd(op) || isRegDisp(op) || isRegOff(op));
472        } else {
473          return false;
474        }
475      }
476    
477      /**
478       *  Return the condition bits of a given optimizing compiler
479       * condition operand.  This method returns the IA32 ISA bits
480       * representing a given condition operand, suitable for passing to
481       * the Assembler to encode into the opcode of a SET, Jcc or
482       * CMOV instruction.  This being IA32, there are of course
483       * exceptions in the binary encoding of conditions (see FCMOV),
484       * but the Assembler handles that.  This function assumes its
485       * argument is an IA32ConditionOperand, and will blow up if it
486       * is not.
487       *
488       * @param op the operand being queried
489       * @return the bits that (usually) represent the given condition
490       * in the IA32 ISA */
491      byte getCond(Operand op) {
492        return ((IA32ConditionOperand) op).value;
493      }
494    
495      /**
496       *  Is the given operand an IA32 condition operand?
497       *
498       * @param op the operand being queried
499       * @return true if op is an IA32 condition operand
500       */
501      boolean isCond(Operand op) {
502        return (op instanceof IA32ConditionOperand);
503      }
504    
505      /**
506       *  Return the label representing the target of the given branch
507       * operand.  These labels are used to represent branch targets
508       * that have not yet been assembled, and so cannot be given
509       * concrete machine code offsets.  All instructions are nunbered
510       * just prior to assembly, and these numbers are used as labels.
511       * This method also returns 0 (not a valid label) for int
512       * constants to simplify generation of branches (the branch
513       * generation code will ignore this invalid label; it is used to
514       * prevent type exceptions).  This method assumes its operand is a
515       * branch operand (or an int) and will blow up if it is not.
516       *
517       * @param op the branch operand being queried
518       * @return the label representing the branch target
519       */
520      int getLabel(Operand op) {
521        if (op instanceof IntConstantOperand) {
522          // used by ImmOrLabel stuff
523          return 0;
524        } else {
525          if (op.asBranch().target.getmcOffset() < 0) {
526            return -op.asBranch().target.getmcOffset();
527          } else {
528            return -1;
529          }
530        }
531      }
532    
533      /**
534       *  Is the given operand a branch target that requires a label?
535       *
536       * @see #getLabel
537       *
538       * @param op the operand being queried
539       * @return true if it represents a branch requiring a label target
540       */
541      boolean isLabel(Operand op) {
542        return (op instanceof BranchOperand && op.asBranch().target.getmcOffset() < 0);
543      }
544    
545      /**
546       *  Is the given operand a branch target?
547       *
548       * @see #getLabel
549       * @see #isLabel
550       *
551       * @param op the operand being queried
552       * @return true if it represents a branch target
553       */
554      @NoInline
555      boolean isImmOrLabel(Operand op) {
556        // TODO: Remove NoInlinePragma, work around for leave SSA bug
557        return (isImm(op) || isLabel(op));
558      }
559    
560      /**
561       * Does the given instruction operate upon byte-sized data?  The
562       * opt compiler does not represent the size of register data, so
563       * this method typically looks at the memory operand, if any, and
564       * checks whether that is a byte.  This does not work for the
565       * size-converting moves (MOVSX and MOVZX), and those instructions
566       * use the operator convention that __b on the end of the operator
567       * name means operate upon byte data.
568       *
569       * @param inst the instruction being queried
570       * @return true if inst operates upon byte data
571       */
572      boolean isByte(Instruction inst) {
573        for(Operator opr : byteSizeOperators){
574          if (opr == inst.operator) {
575            return true;
576          }
577        }
578    
579        for (int i = 0; i < inst.getNumberOfOperands(); i++) {
580          Operand op = inst.getOperand(i);
581          if (op instanceof MemoryOperand) {
582            return (((MemoryOperand) op).size == 1);
583          }
584        }
585    
586        return false;
587      }
588    
589      /**
590       * Does the given instruction operate upon word-sized data?  The
591       * opt compiler does not represent the size of register data, so
592       * this method typically looks at the memory operand, if any, and
593       * checks whether that is a word.  This does not work for the
594       * size-converting moves (MOVSX and MOVZX), and those instructions
595       * use the operator convention that __w on the end of the operator
596       * name means operate upon word data.
597       *
598       * @param inst the instruction being queried
599       * @return true if inst operates upon word data
600       */
601      boolean isWord(Instruction inst) {
602        for(Operator opr : wordSizeOperators){
603          if (opr == inst.operator) {
604            return true;
605          }
606        }
607    
608        for (int i = 0; i < inst.getNumberOfOperands(); i++) {
609          Operand op = inst.getOperand(i);
610          if (op instanceof MemoryOperand) {
611            return (((MemoryOperand) op).size == 2);
612          }
613        }
614    
615        return false;
616      }
617    
618      /**
619       *  Does the given instruction operate upon quad-sized data?  The
620       * opt compiler does not represent the size of register data, so
621       * this method typically looks at the memory operand, if any, and
622       * checks whether that is a byte.  This method also recognizes
623       * the operator convention that __q on the end of the operator
624       * name means operate upon quad data; no operator currently uses
625       * this convention.
626       *
627       * @param inst the instruction being queried
628       * @return true if inst operates upon quad data
629       */
630      boolean isQuad(Instruction inst) {
631        for(Operator opr : quadSizeOperators){
632          if (opr == inst.operator) {
633            return true;
634          }
635        }
636    
637        for (int i = 0; i < inst.getNumberOfOperands(); i++) {
638          Operand op = inst.getOperand(i);
639          if (op instanceof MemoryOperand) {
640            return (((MemoryOperand) op).size == 8);
641          }
642        }
643    
644        return false;
645      }
646    
647      /**
648       * Given a forward branch instruction and its target,
649       * determine (conservatively) if the relative offset to the
650       * target is less than 127 bytes
651       * @param start the branch instruction
652       * @param target the value of the mcOffset of the target label
653       * @return true if the relative offset will be less than 127, false otherwise
654       */
655      protected boolean targetIsClose(Instruction start, int target) {
656        Instruction inst = start.nextInstructionInCodeOrder();
657        final int budget = 120; // slight fudge factor could be 127
658        int offset = 0;
659        while (true) {
660          if (offset <= budget) return false;
661          if (inst.getmcOffset() == target) {
662            return true;
663          }
664          offset += estimateSize(inst, offset);
665          inst = inst.nextInstructionInCodeOrder();
666        }
667      }
668    
669      protected int estimateSize(Instruction inst, int offset) {
670        switch (inst.getOpcode()) {
671          case LABEL_opcode:
672            return (4 - offset) & 3; // return size of nop required for alignment
673          case BBEND_opcode:
674          case UNINT_BEGIN_opcode:
675          case UNINT_END_opcode: {
676            // these generate no code
677            return 0;
678          }
679          case IA32_METHODSTART_opcode:
680            return 12;
681          // Generated from the same case in Assembler
682          case IA32_ADC_opcode:
683          case IA32_ADD_opcode:
684          case IA32_AND_opcode:
685          case IA32_OR_opcode:
686          case IA32_SBB_opcode:
687          case IA32_XOR_opcode: {
688            int size = 2; // opcode + modr/m
689            size += operandCost(MIR_BinaryAcc.getResult(inst), true);
690            size += operandCost(MIR_BinaryAcc.getValue(inst), true);
691            return size;
692          }
693          case IA32_CMP_opcode: {
694            int size = 2; // opcode + modr/m
695            size += operandCost(MIR_Compare.getVal1(inst), true);
696            size += operandCost(MIR_Compare.getVal2(inst), true);
697            return size;
698          }
699          case IA32_TEST_opcode: {
700            int size = 2; // opcode + modr/m
701            size += operandCost(MIR_Test.getVal1(inst), false);
702            size += operandCost(MIR_Test.getVal2(inst), false);
703            return size;
704          }
705          case IA32_ADDSD_opcode:
706          case IA32_SUBSD_opcode:
707          case IA32_MULSD_opcode:
708          case IA32_DIVSD_opcode:
709          case IA32_XORPD_opcode:
710          case IA32_SQRTSD_opcode:
711          case IA32_ADDSS_opcode:
712          case IA32_SUBSS_opcode:
713          case IA32_MULSS_opcode:
714          case IA32_DIVSS_opcode:
715          case IA32_XORPS_opcode: {
716            int size = 4; // opcode + modr/m
717            Operand value = MIR_BinaryAcc.getValue(inst);
718            size += operandCost(value, false);
719            return size;
720          }
721          case IA32_UCOMISS_opcode: {
722            int size = 3; // opcode + modr/m
723            Operand val2 = MIR_Compare.getVal2(inst);
724            size += operandCost(val2, false);
725            return size;
726          }
727          case IA32_UCOMISD_opcode: {
728            int size = 4; // opcode + modr/m
729            Operand val2 = MIR_Compare.getVal2(inst);
730            size += operandCost(val2, false);
731            return size;
732          }
733          case IA32_CVTSI2SS_opcode:
734          case IA32_CVTSI2SD_opcode:
735          case IA32_CVTSS2SD_opcode:
736          case IA32_CVTSD2SS_opcode:
737          case IA32_CVTSD2SI_opcode:
738          case IA32_CVTTSD2SI_opcode:
739          case IA32_CVTSS2SI_opcode:
740          case IA32_CVTTSS2SI_opcode: {
741            int size = 4; // opcode + modr/m
742            Operand result = MIR_Unary.getResult(inst);
743            Operand value = MIR_Unary.getVal(inst);
744            size += operandCost(result, false);
745            size += operandCost(value, false);
746            return size;
747          }
748          case IA32_CMPEQSD_opcode:
749          case IA32_CMPLTSD_opcode:
750          case IA32_CMPLESD_opcode:
751          case IA32_CMPUNORDSD_opcode:
752          case IA32_CMPNESD_opcode:
753          case IA32_CMPNLTSD_opcode:
754          case IA32_CMPNLESD_opcode:
755          case IA32_CMPORDSD_opcode:
756          case IA32_CMPEQSS_opcode:
757          case IA32_CMPLTSS_opcode:
758          case IA32_CMPLESS_opcode:
759          case IA32_CMPUNORDSS_opcode:
760          case IA32_CMPNESS_opcode:
761          case IA32_CMPNLTSS_opcode:
762          case IA32_CMPNLESS_opcode:
763          case IA32_CMPORDSS_opcode: {
764            int size = 5; // opcode + modr/m + type
765            Operand value = MIR_BinaryAcc.getValue(inst);
766            size += operandCost(value, false);
767            return size;
768          }
769          case IA32_MOVD_opcode:
770          case IA32_MOVLPD_opcode:
771          case IA32_MOVQ_opcode:
772          case IA32_MOVSS_opcode:
773          case IA32_MOVSD_opcode: {
774            int size = 4; // opcode + modr/m
775            Operand result = MIR_Move.getResult(inst);
776            Operand value = MIR_Move.getValue(inst);
777            size += operandCost(result, false);
778            size += operandCost(value, false);
779            return size;
780          }
781          case IA32_PUSH_opcode: {
782            Operand op = MIR_UnaryNoRes.getVal(inst);
783            int size = 0;
784            if (op instanceof RegisterOperand) {
785              size += 1;
786            } else if (op instanceof IntConstantOperand) {
787              if (fits(((IntConstantOperand) op).value, 8)) {
788                size += 2;
789              } else {
790                size += 5;
791              }
792            } else {
793              size += (2 + operandCost(op, true));
794            }
795            return size;
796          }
797          case IA32_LEA_opcode: {
798            int size = 2; // opcode + 1 byte modr/m
799            size += operandCost(MIR_Lea.getResult(inst), false);
800            size += operandCost(MIR_Lea.getValue(inst), false);
801            return size;
802          }
803          case IA32_MOV_opcode: {
804            int size = 2; // opcode + modr/m
805            Operand result = MIR_Move.getResult(inst);
806            Operand value = MIR_Move.getValue(inst);
807            size += operandCost(result, false);
808            size += operandCost(value, false);
809            return size;
810          }
811          case MIR_LOWTABLESWITCH_opcode:
812            return MIR_LowTableSwitch.getNumberOfTargets(inst)*4 + 14;
813          case IA32_OFFSET_opcode:
814            return 4;
815          case IA32_JCC_opcode:
816          case IA32_JMP_opcode:
817            return 6; // assume long form
818          case IA32_LOCK_opcode:
819            return 1;
820          case IG_PATCH_POINT_opcode:
821            return 8;
822          case IA32_INT_opcode:
823            return 2;
824          case IA32_RET_opcode:
825            return 3;
826          case IA32_CALL_opcode:
827            Operand target = MIR_Call.getTarget(inst);
828            if (isImmOrLabel(target)) {
829              return 5; // opcode + 32bit immediate
830            } else {
831              return 2 + operandCost(target, false); // opcode + modr/m
832            }
833          default: {
834            int size = 3; // 2 bytes opcode + 1 byte modr/m
835            for (OperandEnumeration opEnum = inst.getRootOperands(); opEnum.hasMoreElements();) {
836              Operand op = opEnum.next();
837              size += operandCost(op, false);
838            }
839            return size;
840          }
841        }
842      }
843    
844      private int operandCost(Operand op, boolean shortFormImmediate) {
845        if (op instanceof MemoryOperand) {
846          MemoryOperand mop = (MemoryOperand) op;
847          // If it's a 2byte mem location, we're going to need an override prefix
848          int prefix = mop.size == 2 ? 1 : 0;
849    
850          // Deal with EBP wierdness
851          if (mop.base != null && mop.base.getRegister() == EBP) {
852            if (mop.index != null) {
853              // forced into SIB + 32 bit displacement no matter what disp is
854              return prefix + 5;
855            }
856            if (fits(mop.disp, 8)) {
857              return prefix + 1;
858            } else {
859              return prefix + 4;
860            }
861          }
862          if (mop.index != null && mop.index.getRegister() == EBP) {
863            // forced into SIB + 32 bit displacement no matter what disp is
864            return prefix + 5;
865          }
866    
867          // Deal with ESP wierdness -- requires SIB byte even when index is null
868          if (mop.base != null && mop.base.getRegister() == ESP) {
869            if (fits(mop.disp, 8)) {
870              return prefix + 2;
871            } else {
872              return prefix + 5;
873            }
874          }
875    
876          if (mop.index == null) {
877            // just displacement to worry about
878            if (mop.disp.isZero()) {
879              return prefix + 0;
880            } else if (fits(mop.disp, 8)) {
881              return prefix + 1;
882            } else {
883              return prefix + 4;
884            }
885          } else {
886            // have a SIB
887            if (mop.base == null && mop.scale != 0) {
888              // forced to 32 bit displacement even if it would fit in 8
889              return prefix + 5;
890            } else {
891              if (mop.disp.isZero()) {
892                return prefix + 1;
893              } else if (fits(mop.disp, 8)) {
894                return prefix + 2;
895              } else {
896                return prefix + 5;
897              }
898            }
899          }
900        } else if (op instanceof IntConstantOperand) {
901          if (shortFormImmediate && fits(((IntConstantOperand) op).value, 8)) {
902            return 1;
903          } else {
904            return 4;
905          }
906        } else {
907          return 0;
908        }
909      }
910    
911      /**
912       * Emit the given instruction, assuming that
913       * it is a MIR_CondBranch instruction
914       * and has a JCC operator
915       *
916       * @param inst the instruction to assemble
917       */
918      protected void doJCC(Instruction inst) {
919        byte cond = getCond(MIR_CondBranch.getCond(inst));
920        if (isImm(MIR_CondBranch.getTarget(inst))) {
921          emitJCC_Cond_Imm(cond, getImm(MIR_CondBranch.getTarget(inst)));
922        } else {
923          if (VM.VerifyAssertions && !isLabel(MIR_CondBranch.getTarget(inst))) VM._assert(false, inst.toString());
924          int sourceLabel = -inst.getmcOffset();
925          int targetLabel = getLabel(MIR_CondBranch.getTarget(inst));
926          int delta = targetLabel - sourceLabel;
927          if (VM.VerifyAssertions) VM._assert(delta >= 0);
928          if (delta < 10 || (delta < 90 && targetIsClose(inst, -targetLabel))) {
929            int miStart = mi;
930            ForwardReference r = new ForwardReference.ShortBranch(mi, targetLabel);
931            forwardRefs = ForwardReference.enqueue(forwardRefs, r);
932            setMachineCodes(mi++, (byte) (0x70 + cond));
933            mi += 1; // leave space for displacement
934            if (lister != null) lister.I(miStart, "J" + CONDITION[cond], 0);
935          } else {
936            emitJCC_Cond_Label(cond, targetLabel);
937          }
938        }
939      }
940    
941      /**
942       * Emit the given instruction, assuming that
943       * it is a MIR_Branch instruction
944       * and has a JMP operator
945       *
946       * @param inst the instruction to assemble
947       */
948      protected void doJMP(Instruction inst) {
949        if (isImm(MIR_Branch.getTarget(inst))) {
950          emitJMP_Imm(getImm(MIR_Branch.getTarget(inst)));
951        } else if (isLabel(MIR_Branch.getTarget(inst))) {
952          int sourceLabel = -inst.getmcOffset();
953          int targetLabel = getLabel(MIR_Branch.getTarget(inst));
954          int delta = targetLabel - sourceLabel;
955          if (VM.VerifyAssertions) VM._assert(delta >= 0);
956          if (delta < 10 || (delta < 90 && targetIsClose(inst, -targetLabel))) {
957            int miStart = mi;
958            ForwardReference r = new ForwardReference.ShortBranch(mi, targetLabel);
959            forwardRefs = ForwardReference.enqueue(forwardRefs, r);
960            setMachineCodes(mi++, (byte) 0xEB);
961            mi += 1; // leave space for displacement
962            if (lister != null) lister.I(miStart, "JMP", 0);
963          } else {
964            emitJMP_Label(getLabel(MIR_Branch.getTarget(inst)));
965          }
966        } else if (isReg(MIR_Branch.getTarget(inst))) {
967          emitJMP_Reg(getGPR_Reg(MIR_Branch.getTarget(inst)));
968        } else if (isAbs(MIR_Branch.getTarget(inst))) {
969          emitJMP_Abs(getDisp(MIR_Branch.getTarget(inst)).toWord().toAddress());
970        } else if (isRegDisp(MIR_Branch.getTarget(inst))) {
971          emitJMP_RegDisp(getBase(MIR_Branch.getTarget(inst)), getDisp(MIR_Branch.getTarget(inst)));
972        } else if (isRegOff(MIR_Branch.getTarget(inst))) {
973          emitJMP_RegOff(getIndex(MIR_Branch.getTarget(inst)),
974                         getScale(MIR_Branch.getTarget(inst)),
975                         getDisp(MIR_Branch.getTarget(inst)));
976        } else if (isRegIdx(MIR_Branch.getTarget(inst))) {
977          emitJMP_RegIdx(getBase(MIR_Branch.getTarget(inst)),
978                         getIndex(MIR_Branch.getTarget(inst)),
979                         getScale(MIR_Branch.getTarget(inst)),
980                         getDisp(MIR_Branch.getTarget(inst)));
981        } else if (isRegInd(MIR_Branch.getTarget(inst))) {
982          emitJMP_RegInd(getBase(MIR_Branch.getTarget(inst)));
983        } else {
984          if (VM.VerifyAssertions) VM._assert(false, inst.toString());
985        }
986      }
987    
988      /**
989       * Emit the given instruction, assuming that
990       * it is a MIR_LowTableSwitch instruction
991       * and has a MIR_LOWTABLESWITCH operator
992       *
993       * @param inst the instruction to assemble
994       */
995      protected void doLOWTABLESWITCH(Instruction inst) {
996        int n = MIR_LowTableSwitch.getNumberOfTargets(inst); // n = number of normal cases (0..n-1)
997        GPR ms = GPR.lookup(MIR_LowTableSwitch.getMethodStart(inst).getRegister().number);
998        GPR idx = GPR.lookup(MIR_LowTableSwitch.getIndex(inst).getRegister().number);
999        // idx += [ms + idx<<2 + ??] - we will patch ?? when we know the placement of the table
1000        int toPatchAddress = getMachineCodeIndex();
1001        if (VM.buildFor32Addr()) {
1002          emitMOV_Reg_RegIdx(idx, ms, idx, Assembler.WORD, Offset.fromIntZeroExtend(Integer.MAX_VALUE));
1003          emitADD_Reg_Reg(idx, ms);
1004        } else {
1005          emitMOV_Reg_RegIdx(idx, ms, idx, Assembler.WORD, Offset.fromIntZeroExtend(Integer.MAX_VALUE));
1006          emitADD_Reg_Reg_Quad(idx, ms);
1007        }
1008        // JMP T0
1009        emitJMP_Reg(idx);
1010        emitNOP((4-getMachineCodeIndex()) & 3); // align table
1011        // create table of offsets from start of method
1012        patchSwitchTableDisplacement(toPatchAddress);
1013        for (int i = 0; i < n; i++) {
1014          Operand target = MIR_LowTableSwitch.getTarget(inst, i);
1015          emitOFFSET_Imm_ImmOrLabel(i, getImm(target), getLabel(target));
1016        }
1017      }
1018    
1019      /**
1020       * Debugging support (return a printable representation of the machine code).
1021       *
1022       * @param instr  An integer to be interpreted as a PowerPC instruction
1023       * @param offset the mcoffset (in bytes) of the instruction
1024       */
1025      public String disasm(int instr, int offset) {
1026        OptimizingCompilerException.TODO("Assembler: disassembler");
1027        return null;
1028      }
1029    
1030      /**
1031       * generate machine code into ir.machinecode.
1032       * @param ir the IR to generate
1033       * @param shouldPrint should we print the machine code?
1034       * @return the number of machinecode instructions generated
1035       */
1036      public static int generateCode(IR ir, boolean shouldPrint) {
1037        int count = 0;
1038        AssemblerOpt asm = new AssemblerOpt(count, shouldPrint, ir);
1039    
1040        for (Instruction p = ir.firstInstructionInCodeOrder(); p != null; p = p.nextInstructionInCodeOrder()) {
1041          // Set the mc offset of all instructions to their negative position.
1042          // A positive value in their position means they have been created
1043          // by the assembler.
1044          count++;
1045          p.setmcOffset(-count);
1046          if (p.operator() == Operators.MIR_LOWTABLESWITCH) {
1047            // Table switch kludge, as these will occupy multiple slots in the
1048            // generated assembler
1049            count += MIR_LowTableSwitch.getNumberOfTargets(p);
1050          }
1051        }
1052    
1053        for (Instruction p = ir.firstInstructionInCodeOrder(); p != null; p = p.nextInstructionInCodeOrder()) {
1054          if (DEBUG_ESTIMATE) {
1055            int start = asm.getMachineCodeIndex();
1056            int estimate = asm.estimateSize(p, start);
1057            asm.doInst(p);
1058            int end = asm.getMachineCodeIndex();
1059            if (end - start > estimate) {
1060              VM.sysWriteln("Bad estimate: " + (end - start) + " " + estimate + " " + p);
1061              VM.sysWrite("\tMachine code: ");
1062              asm.writeLastInstruction(start);
1063              VM.sysWriteln();
1064            }
1065          } else {
1066            asm.doInst(p);
1067          }
1068        }
1069    
1070        ir.MIRInfo.machinecode = asm.getMachineCodes();
1071    
1072        return ir.MIRInfo.machinecode.length();
1073      }
1074    
1075    }