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 */ AMD64Address(Register base)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 */ AMD64Address(Register base, int displacement)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 */ AMD64Address(Register base, Register index, Scale scale)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 */ AMD64Address(Register base, Register index, Scale scale, int displacement)91 public AMD64Address(Register base, Register index, Scale scale, int displacement) { 92 this(base, index, scale, displacement, -1); 93 } 94 AMD64Address(Register base, Register index, Scale scale, int displacement, int instructionStartPosition)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 Scale(int value, int log2)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 fromInt(int scale)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 fromShift(int shift)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 toString()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 */ getBase()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 */ getIndex()194 public Register getIndex() { 195 return index; 196 } 197 198 /** 199 * @return Scaling factor for indexing, dependent on target operand size. 200 */ getScale()201 public Scale getScale() { 202 return scale; 203 } 204 205 /** 206 * @return Optional additive displacement. 207 */ getDisplacement()208 public int getDisplacement() { 209 return displacement; 210 } 211 } 212