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.operand;
014
015import org.jikesrvm.compilers.opt.OptimizingCompilerException;
016import org.vmmagic.unboxed.Address;
017import org.vmmagic.unboxed.Offset;
018
019/**
020 * A memory operand.
021 * Used to represent complex addressing modes on CISC machines.
022 * A memory operand contains some set of other operands that are used
023 * in the address calculation.
024 * <p>
025 * May contain 0, 1, or 2 RegisterOperands as well as a scale factor and
026 * displacement.
027 * <p>
028 * The effective address represented by this operand is:
029 * <pre>
030 *     [base] + [index]*(2^scale) + disp
031 * </pre>
032 *
033 * @see Operand
034 */
035public final class MemoryOperand extends Operand {
036
037  /**
038   * The location operand describing this memory access
039   */
040  public LocationOperand loc;
041
042  /**
043   * The guard operand that validates this memory access
044   */
045  public Operand guard;
046
047  /**
048   * The base register (may be {@code null})
049   */
050  public RegisterOperand base;
051
052  /**
053   * The index register (may be {@code null})
054   */
055  public RegisterOperand index;
056
057  /**
058   * The scale value (log power of 2)
059   * valid values are 0,1,2,3
060   */
061  public byte scale;
062
063  /**
064   * The displacement
065   */
066  public Offset disp;
067
068  /**
069   * Number of bytes being accessed (1,2,4,8)
070   */
071  public byte size;
072
073  public MemoryOperand(RegisterOperand base, RegisterOperand index, byte scale, Offset disp, byte size,
074                           LocationOperand loc, Operand guard) {
075    this.loc = loc;
076    this.guard = guard;
077    this.base = base;
078    this.index = index;
079    this.scale = scale;
080    this.disp = disp;
081    this.size = size;
082    if (loc != null) loc.instruction = null;
083    if (guard != null) guard.instruction = null;
084    if (base != null) base.instruction = null;
085    if (index != null) index.instruction = null;
086  }
087
088  // Shortcuts for some common addressing modes
089  public static MemoryOperand B(RegisterOperand base, byte size, LocationOperand loc, Operand guard) {
090    return new MemoryOperand(base, null, (byte) 0, Offset.zero(), size, loc, guard);
091  }
092
093  public static MemoryOperand BI(RegisterOperand base, RegisterOperand index, byte size,
094                                     LocationOperand loc, Operand guard) {
095    return new MemoryOperand(base, index, (byte) 0, Offset.zero(), size, loc, guard);
096  }
097
098  public static MemoryOperand BD(RegisterOperand base, Offset disp, byte size, LocationOperand loc,
099                                     Operand guard) {
100    return new MemoryOperand(base, null, (byte) 0, disp, size, loc, guard);
101  }
102
103  public static MemoryOperand BID(RegisterOperand base, RegisterOperand index, Offset disp, byte size,
104                                      LocationOperand loc, Operand guard) {
105    return new MemoryOperand(base, index, (byte) 0, disp, size, loc, guard);
106  }
107
108  public static MemoryOperand BIS(RegisterOperand base, RegisterOperand index, byte scale, byte size,
109                                      LocationOperand loc, Operand guard) {
110    return new MemoryOperand(base, index, scale, Offset.zero(), size, loc, guard);
111  }
112
113  public static MemoryOperand D(Address disp, byte size, LocationOperand loc, Operand guard) {
114    return new MemoryOperand(null, null, (byte) 0, disp.toWord().toOffset(), size, loc, guard);
115  }
116
117  public static MemoryOperand I(RegisterOperand base, byte size, LocationOperand loc, Operand guard) {
118    return new MemoryOperand(base, null, (byte) 0, Offset.zero(), size, loc, guard);
119  }
120
121  @Override
122  public Operand copy() {
123    RegisterOperand newBase = (base != null) ? (RegisterOperand) base.copy() : null;
124    RegisterOperand newIndex = (index != null) ? (RegisterOperand) index.copy() : null;
125    LocationOperand newLoc = (loc != null) ? (LocationOperand) loc.copy() : null;
126    Operand newGuard = (guard != null) ? guard.copy() : null;
127    return new MemoryOperand(newBase, newIndex, scale, disp, size, newLoc, newGuard);
128  }
129
130  @Override
131  public boolean similar(Operand op) {
132    if (op instanceof MemoryOperand) {
133      MemoryOperand mop = (MemoryOperand) op;
134      if (base == null) {
135        if (mop.base != null) return false;
136      } else {
137        if (mop.base == null) return false;
138        if (!base.similar(mop.base)) return false;
139      }
140      if (index == null) {
141        if (mop.index != null) return false;
142      } else {
143        if (mop.index == null) return false;
144        if (!index.similar(mop.index)) return false;
145      }
146      return (mop.scale == scale) && (mop.disp.EQ(disp)) && (mop.size == size);
147    } else {
148      return false;
149    }
150  }
151
152  /**
153   * Return a string rep of the operand (ie the effective address)
154   */
155  @Override
156  public String toString() {
157    String addr = (base == null) ? "<0" : "<[" + base + "]";
158    if (index != null) {
159      addr += "+[" + index;
160      switch (scale) {
161        case 0:
162          addr += "]";
163          break;
164        case 1:
165          addr += "*2]";
166          break;
167        case 2:
168          addr += "*4]";
169          break;
170        case 3:
171          addr += "*8]";
172          break;
173        default:
174          OptimizingCompilerException.UNREACHABLE();
175      }
176    }
177    if (!disp.isZero()) {
178      addr += "+" + disp.toInt();
179    }
180    switch (size) {
181      case 1:
182        addr += ">B";
183        break;
184      case 2:
185        addr += ">W";
186        break;
187      case 4:
188        addr += ">DW";
189        break;
190      case 8:
191        addr += ">QW";
192        break;
193      case 16:
194        addr += ">PARAGRAPH";
195        break;
196      default:
197        OptimizingCompilerException.UNREACHABLE();
198    }
199    if (loc != null && guard != null) {
200      addr += " (" + loc + ", " + guard + ")";
201    } else if (loc != null) {
202      addr += " (" + loc + ")";
203    } else if (guard != null) {
204      addr += " (" + guard + ")";
205    }
206    return addr;
207  }
208}