1/*
2 * Copyright (c) 2009, 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 jdk.vm.ci.code;
24
25import java.nio.ByteOrder;
26
27import jdk.vm.ci.code.Register.RegisterCategory;
28import jdk.vm.ci.meta.JavaKind;
29import jdk.vm.ci.meta.PlatformKind;
30
31/**
32 * Represents a CPU architecture, including information such as its endianness, CPU registers, word
33 * width, etc.
34 */
35public abstract class Architecture {
36
37    /**
38     * The architecture specific type of a native word.
39     */
40    private final PlatformKind wordKind;
41
42    /**
43     * The name of this architecture (e.g. "AMD64", "SPARCv9").
44     */
45    private final String name;
46
47    /**
48     * List of all available registers on this architecture. The index of each register in this list
49     * is equal to its {@linkplain Register#number number}.
50     */
51    private final RegisterArray registers;
52
53    /**
54     * The byte ordering can be either little or big endian.
55     */
56    private final ByteOrder byteOrder;
57
58    /**
59     * Whether the architecture supports unaligned memory accesses.
60     */
61    private final boolean unalignedMemoryAccess;
62
63    /**
64     * Mask of the barrier constants denoting the barriers that are not required to be explicitly
65     * inserted under this architecture.
66     */
67    private final int implicitMemoryBarriers;
68
69    /**
70     * Offset in bytes from the beginning of a call instruction to the displacement.
71     */
72    private final int machineCodeCallDisplacementOffset;
73
74    /**
75     * The size of the return address pushed to the stack by a call instruction. A value of 0
76     * denotes that call linkage uses registers instead (e.g. SPARC).
77     */
78    private final int returnAddressSize;
79
80    protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, RegisterArray registers, int implicitMemoryBarriers,
81                    int nativeCallDisplacementOffset,
82                    int returnAddressSize) {
83        this.name = name;
84        this.registers = registers;
85        this.wordKind = wordKind;
86        this.byteOrder = byteOrder;
87        this.unalignedMemoryAccess = unalignedMemoryAccess;
88        this.implicitMemoryBarriers = implicitMemoryBarriers;
89        this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset;
90        this.returnAddressSize = returnAddressSize;
91    }
92
93    /**
94     * Converts this architecture to a string.
95     *
96     * @return the string representation of this architecture
97     */
98    @Override
99    public final String toString() {
100        return getName().toLowerCase();
101    }
102
103    /**
104     * Gets the natural size of words (typically registers and pointers) of this architecture, in
105     * bytes.
106     */
107    public int getWordSize() {
108        return wordKind.getSizeInBytes();
109    }
110
111    public PlatformKind getWordKind() {
112        return wordKind;
113    }
114
115    /**
116     * Gets the name of this architecture.
117     */
118    public String getName() {
119        return name;
120    }
121
122    /**
123     * Gets the list of all registers that exist on this architecture. This contains all registers
124     * that exist in the specification of this architecture. Not all of them may be available on
125     * this particular architecture instance. The index of each register in this list is equal to
126     * its {@linkplain Register#number number}.
127     */
128    public RegisterArray getRegisters() {
129        return registers;
130    }
131
132    /**
133     * Gets a list of all registers available for storing values on this architecture. This may be a
134     * subset of {@link #getRegisters()}, depending on the capabilities of this particular CPU.
135     */
136    public RegisterArray getAvailableValueRegisters() {
137        return getRegisters();
138    }
139
140    public ByteOrder getByteOrder() {
141        return byteOrder;
142    }
143
144    /**
145     * @return true if the architecture supports unaligned memory accesses.
146     */
147    public boolean supportsUnalignedMemoryAccess() {
148        return unalignedMemoryAccess;
149    }
150
151    /**
152     * Gets the size of the return address pushed to the stack by a call instruction. A value of 0
153     * denotes that call linkage uses registers instead.
154     */
155    public int getReturnAddressSize() {
156        return returnAddressSize;
157    }
158
159    /**
160     * Gets the offset in bytes from the beginning of a call instruction to the displacement.
161     */
162    public int getMachineCodeCallDisplacementOffset() {
163        return machineCodeCallDisplacementOffset;
164    }
165
166    /**
167     * Determines the barriers in a given barrier mask that are explicitly required on this
168     * architecture.
169     *
170     * @param barriers a mask of the barrier constants
171     * @return the value of {@code barriers} minus the barriers unnecessary on this architecture
172     */
173    public final int requiredBarriers(int barriers) {
174        return barriers & ~implicitMemoryBarriers;
175    }
176
177    /**
178     * Determine whether a kind can be stored in a register of a given category.
179     *
180     * @param category the category of the register
181     * @param kind the kind that should be stored in the register
182     */
183    public abstract boolean canStoreValue(RegisterCategory category, PlatformKind kind);
184
185    /**
186     * Return the largest kind that can be stored in a register of a given category.
187     *
188     * @param category the category of the register
189     * @return the largest kind that can be stored in a register {@code category}
190     */
191    public abstract PlatformKind getLargestStorableKind(RegisterCategory category);
192
193    /**
194     * Return the {@link PlatformKind} that is used to store values of a given {@link JavaKind}.
195     */
196    public abstract PlatformKind getPlatformKind(JavaKind javaKind);
197
198    @Override
199    public final boolean equals(Object obj) {
200        if (obj == this) {
201            return true;
202        }
203        if (obj instanceof Architecture) {
204            Architecture that = (Architecture) obj;
205            if (this.name.equals(that.name)) {
206                assert this.byteOrder.equals(that.byteOrder);
207                assert this.implicitMemoryBarriers == that.implicitMemoryBarriers;
208                assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset;
209                assert this.registers.equals(that.registers);
210                assert this.returnAddressSize == that.returnAddressSize;
211                assert this.unalignedMemoryAccess == that.unalignedMemoryAccess;
212                assert this.wordKind == that.wordKind;
213                return true;
214            }
215        }
216        return false;
217    }
218
219    @Override
220    public final int hashCode() {
221        return name.hashCode();
222    }
223}
224