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.operand;
014    
015    import org.jikesrvm.compilers.opt.OptimizingCompilerException;
016    import org.vmmagic.unboxed.Address;
017    import 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     */
035    public 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    }