AMD64Address.java revision 12651:6ef01bd40ce2
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 */
23package org.graalvm.compiler.asm.amd64;
24
25import jdk.vm.ci.code.Register;
26
27import 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 */
34public 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}
198