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.ir.ia32;
014    
015    import java.util.Enumeration;
016    import org.jikesrvm.compilers.opt.OptimizingCompilerException;
017    import org.jikesrvm.compilers.opt.ir.IR;
018    import org.jikesrvm.compilers.opt.ir.Operator;
019    import org.jikesrvm.compilers.opt.ir.Register;
020    import org.vmmagic.pragma.Pure;
021    
022    /**
023     * This class provides utilities to record defs and uses of physical
024     * registers by IR operators.
025     */
026    public abstract class PhysicalDefUse {
027    
028      // constants used to encode defs/uses of physical registers
029      /** Default empty mask */
030      public static final int mask = 0x0000;
031      /** AF in the eflags is used/defined */
032      public static final int maskAF = 0x0001;
033      /** CF in the eflags is used/defined */
034      public static final int maskCF = 0x0002;
035      /** OF in the eflags is used/defined */
036      public static final int maskOF = 0x0004;
037      /** PF in the eflags is used/defined */
038      public static final int maskPF = 0x0008;
039      /** SF in the eflags is used/defined */
040      public static final int maskSF = 0x0010;
041      /** ZF in the eflags is used/defined */
042      public static final int maskZF = 0x0020;
043      /** C0 in the x87 FPU is used/defined */
044      public static final int maskC0 = 0x0040;
045      /** C1 in the x87 FPU is used/defined */
046      public static final int maskC1 = 0x0080;
047      /** C2 in the x87 FPU is used/defined */
048      public static final int maskC2 = 0x0100;
049      /** C3 in the x87 FPU is used/defined */
050      public static final int maskC3 = 0x0200;
051      /** The processor register is used/defined */
052      public static final int maskTR = 0x0400;
053      /** The ESP register is used/defined */
054      public static final int maskESP= 0x0800;
055      /* Meta mask for the enumeration. */
056      /** First mask bit */
057      private static final int maskHIGH = 0x0800;
058      /** Mask for all bits */
059      private static final int maskALL = 0x0FFF;
060    
061      public static final int maskCF_OF = maskCF | maskOF;
062      public static final int maskCF_PF_ZF = maskCF | maskPF | maskZF;
063      public static final int maskCF_OF_PF_SF_ZF = maskCF | maskOF | maskPF | maskSF | maskZF;
064      public static final int maskAF_OF_PF_SF_ZF = maskAF | maskOF | maskPF | maskSF | maskZF;
065      public static final int maskAF_CF_OF_PF_SF_ZF = maskAF | maskCF | maskOF | maskPF | maskSF | maskZF;
066      public static final int maskC0_C1_C2_C3 = maskC0 | maskC1 | maskC2 | maskC3;
067      public static final int maskcallDefs = maskAF_CF_OF_PF_SF_ZF | maskESP;
068      public static final int maskcallUses = maskESP;
069      public static final int maskIEEEMagicUses = mask;
070      /** Uses mask used by dependence graph to show a yield point */
071      public static final int maskTSPUses = maskESP;
072      /** Definitions mask used by dependence graph to show a yield point */
073      public static final int maskTSPDefs = maskAF_CF_OF_PF_SF_ZF | maskTR | maskESP;
074    
075      /**
076       * @return whether or not an Operator uses the EFLAGS
077       */
078      public static boolean usesEFLAGS(Operator op) {
079        return (op.implicitUses & maskAF_CF_OF_PF_SF_ZF) != 0;
080      }
081    
082      /**
083       * @return whether or not an Operator uses the EFLAGS
084       */
085      public static boolean definesEFLAGS(Operator op) {
086        return (op.implicitDefs & maskAF_CF_OF_PF_SF_ZF) != 0;
087      }
088    
089      /**
090       * @return whether or not an Operator implicitly uses or defines ESP
091       */
092      public static boolean usesOrDefinesESP(Operator op) {
093        return ((op.implicitUses & maskESP) != 0) || ((op.implicitDefs & maskESP) != 0);
094      }
095      /**
096       * @return a string representation of the physical registers encoded by
097       * an integer
098       */
099      @Pure
100      public static String getString(int code) {
101        if (code == mask) return "";
102        if (code == maskAF_CF_OF_PF_SF_ZF) return " AF CF OF PF SF ZF";
103        // Not a common case, construct it...
104        String s = "";
105        if ((code & maskAF) != 0) s += " AF";
106        if ((code & maskCF) != 0) s += " CF";
107        if ((code & maskOF) != 0) s += " OF";
108        if ((code & maskPF) != 0) s += " PF";
109        if ((code & maskZF) != 0) s += " ZF";
110        if ((code & maskC0) != 0) s += " CO";
111        if ((code & maskC1) != 0) s += " C1";
112        if ((code & maskC2) != 0) s += " C2";
113        if ((code & maskC3) != 0) s += " C3";
114        if ((code & maskTR) != 0) s += " TR";
115        if ((code & maskESP) != 0) s += " ESP";
116        return s;
117      }
118    
119      /**
120       * @param code an integer that encodes a set of physical registers
121       * @param ir the governing IR
122       * @return an enumeration of the physical registers embodied by a code
123       */
124      public static PDUEnumeration enumerate(int code, IR ir) {
125        return new PDUEnumeration(code, ir);
126      }
127    
128      /**
129       * @param ir the governing IR
130       * @return an enumeration of all physical registers that code be
131       *         implicitly defed/used
132       */
133      public static PDUEnumeration enumerateAllImplicitDefUses(IR ir) {
134        return new PDUEnumeration(maskALL, ir);
135      }
136    
137      /**
138       * A class to enumerate physical registers based on a code.
139       */
140      public static final class PDUEnumeration implements Enumeration<Register> {
141        private int code;
142        private int curMask;
143        private PhysicalRegisterSet phys;
144    
145        PDUEnumeration(int c, IR ir) {
146          phys = ir.regpool.getPhysicalRegisterSet();
147          code = c;
148          curMask = maskHIGH;
149        }
150    
151        @Override
152        public boolean hasMoreElements() {
153          return code != 0;
154        }
155    
156        @Override
157        public Register nextElement() {
158          while (true) {
159            int curBit = code & curMask;
160            code -= curBit;
161            curMask = curMask >> 1;
162            if (curBit != 0) return getReg(curBit, phys);
163          }
164        }
165    
166        // Artificially make static to enable scalar replacement of
167        // enumeration object without requiring this method to be inlined.
168        private static Register getReg(int m, PhysicalRegisterSet phys) {
169          switch (m) {
170            case maskAF:
171              return phys.getAF();
172            case maskCF:
173              return phys.getCF();
174            case maskOF:
175              return phys.getOF();
176            case maskPF:
177              return phys.getPF();
178            case maskSF:
179              return phys.getSF();
180            case maskZF:
181              return phys.getZF();
182            case maskC0:
183              return phys.getC0();
184            case maskC1:
185              return phys.getC1();
186            case maskC2:
187              return phys.getC2();
188            case maskC3:
189              return phys.getC3();
190            case maskTR:
191              return phys.getTR();
192            case maskESP:
193              return phys.getESP();
194          }
195          OptimizingCompilerException.UNREACHABLE();
196          return null;
197        }
198      }
199    }