1 /*
   2  * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.asm.amd64;
  24 
  25 import jdk.vm.ci.code.Register;
  26 
  27 import org.graalvm.compiler.asm.AbstractAddress;
  28 
  29 /**
  30  * Represents an address in target machine memory, specified via some combination of a base
  31  * register, an index register, a displacement and a scale. Note that the base and index registers
  32  * may be a variable that will get a register assigned later by the register allocator.
  33  */
  34 public final class AMD64Address extends AbstractAddress {
  35 
  36     private final Register base;
  37     private final Register index;
  38     private final Scale scale;
  39     private final int displacement;
  40 
  41     /**
  42      * The start of the instruction, i.e., the value that is used as the key for looking up
  43      * placeholder patching information. Only used for {@link AMD64Assembler#getPlaceholder
  44      * placeholder addresses}.
  45      */
  46     final int instructionStartPosition;
  47 
  48     /**
  49      * Creates an {@link AMD64Address} with given base register, no scaling and no displacement.
  50      *
  51      * @param base the base register
  52      */
  53     public AMD64Address(Register base) {
  54         this(base, Register.None, Scale.Times1, 0);
  55     }
  56 
  57     /**
  58      * Creates an {@link AMD64Address} with given base register, no scaling and a given
  59      * displacement.
  60      *
  61      * @param base the base register
  62      * @param displacement the displacement
  63      */
  64     public AMD64Address(Register base, int displacement) {
  65         this(base, Register.None, Scale.Times1, displacement);
  66     }
  67 
  68     /**
  69      * Creates an {@link AMD64Address} with given base and index registers, scaling and 0
  70      * displacement.
  71      *
  72      * @param base the base register
  73      * @param index the index register
  74      * @param scale the scaling factor
  75      */
  76     public AMD64Address(Register base, Register index, Scale scale) {
  77         this(base, index, scale, 0, -1);
  78     }
  79 
  80     /**
  81      * Creates an {@link AMD64Address} with given base and index registers, scaling and
  82      * displacement. This is the most general constructor.
  83      *
  84      * @param base the base register
  85      * @param index the index register
  86      * @param scale the scaling factor
  87      * @param displacement the displacement
  88      */
  89     public AMD64Address(Register base, Register index, Scale scale, int displacement) {
  90         this(base, index, scale, displacement, -1);
  91     }
  92 
  93     AMD64Address(Register base, Register index, Scale scale, int displacement, int instructionStartPosition) {
  94         this.base = base;
  95         this.index = index;
  96         this.scale = scale;
  97         this.displacement = displacement;
  98         this.instructionStartPosition = instructionStartPosition;
  99 
 100         assert scale != null;
 101     }
 102 
 103     /**
 104      * A scaling factor used in the SIB addressing mode.
 105      */
 106     public enum Scale {
 107         Times1(1, 0),
 108         Times2(2, 1),
 109         Times4(4, 2),
 110         Times8(8, 3);
 111 
 112         Scale(int value, int log2) {
 113             this.value = value;
 114             this.log2 = log2;
 115         }
 116 
 117         /**
 118          * The value (or multiplier) of this scale.
 119          */
 120         public final int value;
 121 
 122         /**
 123          * The {@linkplain #value value} of this scale log 2.
 124          */
 125         public final int log2;
 126 
 127         public static Scale fromInt(int scale) {
 128             switch (scale) {
 129                 case 1:
 130                     return Times1;
 131                 case 2:
 132                     return Times2;
 133                 case 4:
 134                     return Times4;
 135                 case 8:
 136                     return Times8;
 137                 default:
 138                     return null;
 139             }
 140         }
 141 
 142         public static Scale fromShift(int shift) {
 143             switch (shift) {
 144                 case 0:
 145                     return Times1;
 146                 case 1:
 147                     return Times2;
 148                 case 2:
 149                     return Times4;
 150                 case 3:
 151                     return Times8;
 152                 default:
 153                     return null;
 154             }
 155         }
 156     }
 157 
 158     @Override
 159     public String toString() {
 160         StringBuilder s = new StringBuilder();
 161         s.append("[");
 162         String sep = "";
 163         if (!getBase().equals(Register.None)) {
 164             s.append(getBase());
 165             sep = " + ";
 166         }
 167         if (!getIndex().equals(Register.None)) {
 168             s.append(sep).append(getIndex()).append(" * ").append(getScale().value);
 169             sep = " + ";
 170         }
 171         if (getDisplacement() < 0) {
 172             s.append(" - ").append(-getDisplacement());
 173         } else if (getDisplacement() > 0) {
 174             s.append(sep).append(getDisplacement());
 175         }
 176         s.append("]");
 177         return s.toString();
 178     }
 179 
 180     /**
 181      * @return Base register that defines the start of the address computation. If not present, is
 182      *         denoted by {@link Register#None}.
 183      */
 184     public Register getBase() {
 185         return base;
 186     }
 187 
 188     /**
 189      * @return Index register, the value of which (possibly scaled by {@link #getScale}) is added to
 190      *         {@link #getBase}. If not present, is denoted by {@link Register#None}.
 191      */
 192     public Register getIndex() {
 193         return index;
 194     }
 195 
 196     /**
 197      * @return Scaling factor for indexing, dependent on target operand size.
 198      */
 199     public Scale getScale() {
 200         return scale;
 201     }
 202 
 203     /**
 204      * @return Optional additive displacement.
 205      */
 206     public int getDisplacement() {
 207         return displacement;
 208     }
 209 }