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
  70      * displacement. This is the most general constructor.
  71      *
  72      * @param base the base register
  73      * @param index the index register
  74      * @param scale the scaling factor
  75      * @param displacement the displacement
  76      */
  77     public AMD64Address(Register base, Register index, Scale scale, int displacement) {
  78         this(base, index, scale, displacement, -1);
  79     }
  80 
  81     AMD64Address(Register base, Register index, Scale scale, int displacement, int instructionStartPosition) {
  82         this.base = base;
  83         this.index = index;
  84         this.scale = scale;
  85         this.displacement = displacement;
  86         this.instructionStartPosition = instructionStartPosition;
  87 
  88         assert scale != null;
  89     }
  90 
  91     /**
  92      * A scaling factor used in the SIB addressing mode.
  93      */
  94     public enum Scale {
  95         Times1(1, 0),
  96         Times2(2, 1),
  97         Times4(4, 2),
  98         Times8(8, 3);
  99 
 100         Scale(int value, int log2) {
 101             this.value = value;
 102             this.log2 = log2;
 103         }
 104 
 105         /**
 106          * The value (or multiplier) of this scale.
 107          */
 108         public final int value;
 109 
 110         /**
 111          * The {@linkplain #value value} of this scale log 2.
 112          */
 113         public final int log2;
 114 
 115         public static Scale fromInt(int scale) {
 116             switch (scale) {
 117                 case 1:
 118                     return Times1;
 119                 case 2:
 120                     return Times2;
 121                 case 4:
 122                     return Times4;
 123                 case 8:
 124                     return Times8;
 125                 default:
 126                     return null;
 127             }
 128         }
 129 
 130         public static Scale fromShift(int shift) {
 131             switch (shift) {
 132                 case 0:
 133                     return Times1;
 134                 case 1:
 135                     return Times2;
 136                 case 2:
 137                     return Times4;
 138                 case 3:
 139                     return Times8;
 140                 default:
 141                     return null;
 142             }
 143         }
 144     }
 145 
 146     @Override
 147     public String toString() {
 148         StringBuilder s = new StringBuilder();
 149         s.append("[");
 150         String sep = "";
 151         if (!getBase().equals(Register.None)) {
 152             s.append(getBase());
 153             sep = " + ";
 154         }
 155         if (!getIndex().equals(Register.None)) {
 156             s.append(sep).append(getIndex()).append(" * ").append(getScale().value);
 157             sep = " + ";
 158         }
 159         if (getDisplacement() < 0) {
 160             s.append(" - ").append(-getDisplacement());
 161         } else if (getDisplacement() > 0) {
 162             s.append(sep).append(getDisplacement());
 163         }
 164         s.append("]");
 165         return s.toString();
 166     }
 167 
 168     /**
 169      * @return Base register that defines the start of the address computation. If not present, is
 170      *         denoted by {@link Register#None}.
 171      */
 172     public Register getBase() {
 173         return base;
 174     }
 175 
 176     /**
 177      * @return Index register, the value of which (possibly scaled by {@link #getScale}) is added to
 178      *         {@link #getBase}. If not present, is denoted by {@link Register#None}.
 179      */
 180     public Register getIndex() {
 181         return index;
 182     }
 183 
 184     /**
 185      * @return Scaling factor for indexing, dependent on target operand size.
 186      */
 187     public Scale getScale() {
 188         return scale;
 189     }
 190 
 191     /**
 192      * @return Optional additive displacement.
 193      */
 194     public int getDisplacement() {
 195         return displacement;
 196     }
 197 }