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 
  24 
  25 package org.graalvm.compiler.asm.amd64;
  26 
  27 import jdk.vm.ci.code.Register;
  28 
  29 import org.graalvm.compiler.asm.AbstractAddress;
  30 
  31 /**
  32  * Represents an address in target machine memory, specified via some combination of a base
  33  * register, an index register, a displacement and a scale. Note that the base and index registers
  34  * may be a variable that will get a register assigned later by the register allocator.
  35  */
  36 public final class AMD64Address extends AbstractAddress {
  37 
  38     private final Register base;
  39     private final Register index;
  40     private final Scale scale;
  41     private final int displacement;
  42 
  43     /**
  44      * The start of the instruction, i.e., the value that is used as the key for looking up
  45      * placeholder patching information. Only used for {@link AMD64Assembler#getPlaceholder
  46      * placeholder addresses}.
  47      */
  48     final int instructionStartPosition;
  49 
  50     /**
  51      * Creates an {@link AMD64Address} with given base register, no scaling and no displacement.
  52      *
  53      * @param base the base register
  54      */
  55     public AMD64Address(Register base) {
  56         this(base, Register.None, Scale.Times1, 0);
  57     }
  58 
  59     /**
  60      * Creates an {@link AMD64Address} with given base register, no scaling and a given
  61      * displacement.
  62      *
  63      * @param base the base register
  64      * @param displacement the displacement
  65      */
  66     public AMD64Address(Register base, int displacement) {
  67         this(base, Register.None, Scale.Times1, displacement);
  68     }
  69 
  70     /**
  71      * Creates an {@link AMD64Address} with given base and index registers, scaling and 0
  72      * displacement.
  73      *
  74      * @param base the base register
  75      * @param index the index register
  76      * @param scale the scaling factor
  77      */
  78     public AMD64Address(Register base, Register index, Scale scale) {
  79         this(base, index, scale, 0, -1);
  80     }
  81 
  82     /**
  83      * Creates an {@link AMD64Address} with given base and index registers, scaling and
  84      * displacement. This is the most general constructor.
  85      *
  86      * @param base the base register
  87      * @param index the index register
  88      * @param scale the scaling factor
  89      * @param displacement the displacement
  90      */
  91     public AMD64Address(Register base, Register index, Scale scale, int displacement) {
  92         this(base, index, scale, displacement, -1);
  93     }
  94 
  95     AMD64Address(Register base, Register index, Scale scale, int displacement, int instructionStartPosition) {
  96         this.base = base;
  97         this.index = index;
  98         this.scale = scale;
  99         this.displacement = displacement;
 100         this.instructionStartPosition = instructionStartPosition;
 101 
 102         assert scale != null;
 103     }
 104 
 105     /**
 106      * A scaling factor used in the SIB addressing mode.
 107      */
 108     public enum Scale {
 109         Times1(1, 0),
 110         Times2(2, 1),
 111         Times4(4, 2),
 112         Times8(8, 3);
 113 
 114         Scale(int value, int log2) {
 115             this.value = value;
 116             this.log2 = log2;
 117         }
 118 
 119         /**
 120          * The value (or multiplier) of this scale.
 121          */
 122         public final int value;
 123 
 124         /**
 125          * The {@linkplain #value value} of this scale log 2.
 126          */
 127         public final int log2;
 128 
 129         public static Scale fromInt(int scale) {
 130             switch (scale) {
 131                 case 1:
 132                     return Times1;
 133                 case 2:
 134                     return Times2;
 135                 case 4:
 136                     return Times4;
 137                 case 8:
 138                     return Times8;
 139                 default:
 140                     return null;
 141             }
 142         }
 143 
 144         public static Scale fromShift(int shift) {
 145             switch (shift) {
 146                 case 0:
 147                     return Times1;
 148                 case 1:
 149                     return Times2;
 150                 case 2:
 151                     return Times4;
 152                 case 3:
 153                     return Times8;
 154                 default:
 155                     return null;
 156             }
 157         }
 158     }
 159 
 160     @Override
 161     public String toString() {
 162         StringBuilder s = new StringBuilder();
 163         s.append("[");
 164         String sep = "";
 165         if (!getBase().equals(Register.None)) {
 166             s.append(getBase());
 167             sep = " + ";
 168         }
 169         if (!getIndex().equals(Register.None)) {
 170             s.append(sep).append(getIndex()).append(" * ").append(getScale().value);
 171             sep = " + ";
 172         }
 173         if (getDisplacement() < 0) {
 174             s.append(" - ").append(-getDisplacement());
 175         } else if (getDisplacement() > 0) {
 176             s.append(sep).append(getDisplacement());
 177         }
 178         s.append("]");
 179         return s.toString();
 180     }
 181 
 182     /**
 183      * @return Base register that defines the start of the address computation. If not present, is
 184      *         denoted by {@link Register#None}.
 185      */
 186     public Register getBase() {
 187         return base;
 188     }
 189 
 190     /**
 191      * @return Index register, the value of which (possibly scaled by {@link #getScale}) is added to
 192      *         {@link #getBase}. If not present, is denoted by {@link Register#None}.
 193      */
 194     public Register getIndex() {
 195         return index;
 196     }
 197 
 198     /**
 199      * @return Scaling factor for indexing, dependent on target operand size.
 200      */
 201     public Scale getScale() {
 202         return scale;
 203     }
 204 
 205     /**
 206      * @return Optional additive displacement.
 207      */
 208     public int getDisplacement() {
 209         return displacement;
 210     }
 211 }