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 */
013package org.jikesrvm.compilers.opt.ir.ia32;
014
015import java.util.Enumeration;
016import org.jikesrvm.compilers.opt.OptimizingCompilerException;
017import org.jikesrvm.compilers.opt.ir.IR;
018import org.jikesrvm.compilers.opt.ir.Operator;
019import org.jikesrvm.compilers.opt.ir.Register;
020import org.vmmagic.pragma.Pure;
021
022/**
023 * This class provides utilities to record defs and uses of physical
024 * registers by IR operators.
025 */
026public 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  public static boolean usesEFLAGS(Operator op) {
076    return (op.implicitUses & maskAF_CF_OF_PF_SF_ZF) != 0;
077  }
078
079  public static boolean definesEFLAGS(Operator op) {
080    return (op.implicitDefs & maskAF_CF_OF_PF_SF_ZF) != 0;
081  }
082
083  public static boolean usesOrDefinesESP(Operator op) {
084    return ((op.implicitUses & maskESP) != 0) || ((op.implicitDefs & maskESP) != 0);
085  }
086
087  /**
088   * @param code the encoding of physical registers
089   * @return a string representation of the physical registers encoded by
090   * an integer
091   */
092  @Pure
093  public static String getString(int code) {
094    if (code == mask) return "";
095    if (code == maskAF_CF_OF_PF_SF_ZF) return " AF CF OF PF SF ZF";
096    // Not a common case, construct it...
097    String s = "";
098    if ((code & maskAF) != 0) s += " AF";
099    if ((code & maskCF) != 0) s += " CF";
100    if ((code & maskOF) != 0) s += " OF";
101    if ((code & maskPF) != 0) s += " PF";
102    if ((code & maskZF) != 0) s += " ZF";
103    if ((code & maskC0) != 0) s += " CO";
104    if ((code & maskC1) != 0) s += " C1";
105    if ((code & maskC2) != 0) s += " C2";
106    if ((code & maskC3) != 0) s += " C3";
107    if ((code & maskTR) != 0) s += " TR";
108    if ((code & maskESP) != 0) s += " ESP";
109    return s;
110  }
111
112  /**
113   * @param code an integer that encodes a set of physical registers
114   * @param ir the governing IR
115   * @return an enumeration of the physical registers embodied by a code
116   */
117  public static PDUEnumeration enumerate(int code, IR ir) {
118    return new PDUEnumeration(code, ir);
119  }
120
121  /**
122   * @param ir the governing IR
123   * @return an enumeration of all physical registers that code be
124   *         implicitly defed/used
125   */
126  public static PDUEnumeration enumerateAllImplicitDefUses(IR ir) {
127    return new PDUEnumeration(maskALL, ir);
128  }
129
130  /**
131   * A class to enumerate physical registers based on a code.
132   */
133  public static final class PDUEnumeration implements Enumeration<Register> {
134    private int code;
135    private int curMask;
136    private final PhysicalRegisterSet phys;
137
138    PDUEnumeration(int c, IR ir) {
139      phys = (PhysicalRegisterSet)ir.regpool.getPhysicalRegisterSet();
140      code = c;
141      curMask = maskHIGH;
142    }
143
144    @Override
145    public boolean hasMoreElements() {
146      return code != 0;
147    }
148
149    @Override
150    public Register nextElement() {
151      while (true) {
152        int curBit = code & curMask;
153        code -= curBit;
154        curMask = curMask >> 1;
155        if (curBit != 0) return getReg(curBit, phys);
156      }
157    }
158
159    // Artificially make static to enable scalar replacement of
160    // enumeration object without requiring this method to be inlined.
161    private static Register getReg(int m, PhysicalRegisterSet phys) {
162      switch (m) {
163        case maskAF:
164          return phys.getAF();
165        case maskCF:
166          return phys.getCF();
167        case maskOF:
168          return phys.getOF();
169        case maskPF:
170          return phys.getPF();
171        case maskSF:
172          return phys.getSF();
173        case maskZF:
174          return phys.getZF();
175        case maskC0:
176          return phys.getC0();
177        case maskC1:
178          return phys.getC1();
179        case maskC2:
180          return phys.getC2();
181        case maskC3:
182          return phys.getC3();
183        case maskTR:
184          return phys.getTR();
185        case maskESP:
186          return phys.getESP();
187      }
188      OptimizingCompilerException.UNREACHABLE();
189      return null;
190    }
191  }
192}