001/*
002 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package jdk.internal.jvmci.code;
024
025import java.nio.*;
026import java.util.*;
027
028import jdk.internal.jvmci.code.Register.*;
029import jdk.internal.jvmci.meta.*;
030
031/**
032 * Represents a CPU architecture, including information such as its endianness, CPU registers, word
033 * width, etc.
034 */
035public abstract class Architecture {
036
037    /**
038     * The number of entries required in a {@link ReferenceMap} covering all the registers that may
039     * store references. The index of a register in the reference map is given by
040     * {@link Register#getReferenceMapIndex()}.
041     */
042    private final int registerReferenceMapSize;
043
044    /**
045     * Represents the natural size of words (typically registers and pointers) of this architecture,
046     * in bytes.
047     */
048    private final int wordSize;
049
050    /**
051     * The name of this architecture (e.g. "AMD64", "SPARCv9").
052     */
053    private final String name;
054
055    /**
056     * Array of all available registers on this architecture. The index of each register in this
057     * array is equal to its {@linkplain Register#number number}.
058     */
059    private final Register[] registers;
060
061    /**
062     * The byte ordering can be either little or big endian.
063     */
064    private final ByteOrder byteOrder;
065
066    /**
067     * Whether the architecture supports unaligned memory accesses.
068     */
069    private final boolean unalignedMemoryAccess;
070
071    /**
072     * Mask of the barrier constants denoting the barriers that are not required to be explicitly
073     * inserted under this architecture.
074     */
075    private final int implicitMemoryBarriers;
076
077    /**
078     * Offset in bytes from the beginning of a call instruction to the displacement.
079     */
080    private final int machineCodeCallDisplacementOffset;
081
082    /**
083     * The size of the return address pushed to the stack by a call instruction. A value of 0
084     * denotes that call linkage uses registers instead (e.g. SPARC).
085     */
086    private final int returnAddressSize;
087
088    protected Architecture(String name, int wordSize, ByteOrder byteOrder, boolean unalignedMemoryAccess, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset,
089                    int registerReferenceMapSize, int returnAddressSize) {
090        this.name = name;
091        this.registers = registers;
092        this.wordSize = wordSize;
093        this.byteOrder = byteOrder;
094        this.unalignedMemoryAccess = unalignedMemoryAccess;
095        this.implicitMemoryBarriers = implicitMemoryBarriers;
096        this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset;
097        this.registerReferenceMapSize = registerReferenceMapSize;
098        this.returnAddressSize = returnAddressSize;
099    }
100
101    /**
102     * Converts this architecture to a string.
103     *
104     * @return the string representation of this architecture
105     */
106    @Override
107    public final String toString() {
108        return getName().toLowerCase();
109    }
110
111    public int getRegisterReferenceMapSize() {
112        return registerReferenceMapSize;
113    }
114
115    /**
116     * Gets the natural size of words (typically registers and pointers) of this architecture, in
117     * bytes.
118     */
119    public int getWordSize() {
120        return wordSize;
121    }
122
123    /**
124     * Gets the name of this architecture.
125     */
126    public String getName() {
127        return name;
128    }
129
130    /**
131     * Gets an array of all available registers on this architecture. The index of each register in
132     * this array is equal to its {@linkplain Register#number number}.
133     */
134    public Register[] getRegisters() {
135        return registers.clone();
136    }
137
138    public ByteOrder getByteOrder() {
139        return byteOrder;
140    }
141
142    /**
143     * @return true if the architecture supports unaligned memory accesses.
144     */
145    public boolean supportsUnalignedMemoryAccess() {
146        return unalignedMemoryAccess;
147    }
148
149    /**
150     * Gets the size of the return address pushed to the stack by a call instruction. A value of 0
151     * denotes that call linkage uses registers instead.
152     */
153    public int getReturnAddressSize() {
154        return returnAddressSize;
155    }
156
157    /**
158     * Gets the offset in bytes from the beginning of a call instruction to the displacement.
159     */
160    public int getMachineCodeCallDisplacementOffset() {
161        return machineCodeCallDisplacementOffset;
162    }
163
164    /**
165     * Determines the barriers in a given barrier mask that are explicitly required on this
166     * architecture.
167     *
168     * @param barriers a mask of the barrier constants
169     * @return the value of {@code barriers} minus the barriers unnecessary on this architecture
170     */
171    public final int requiredBarriers(int barriers) {
172        return barriers & ~implicitMemoryBarriers;
173    }
174
175    /**
176     * Gets the size in bytes of the specified kind for this target.
177     *
178     * @param kind the kind for which to get the size
179     *
180     * @return the size in bytes of {@code kind}
181     */
182    public int getSizeInBytes(PlatformKind kind) {
183        switch ((Kind) kind) {
184            case Boolean:
185                return 1;
186            case Byte:
187                return 1;
188            case Char:
189                return 2;
190            case Short:
191                return 2;
192            case Int:
193                return 4;
194            case Long:
195                return 8;
196            case Float:
197                return 4;
198            case Double:
199                return 8;
200            case Object:
201                return wordSize;
202            default:
203                return 0;
204        }
205    }
206
207    /**
208     * Determine whether a kind can be stored in a register of a given category.
209     *
210     * @param category the category of the register
211     * @param kind the kind that should be stored in the register
212     */
213    public abstract boolean canStoreValue(RegisterCategory category, PlatformKind kind);
214
215    /**
216     * Return the largest kind that can be stored in a register of a given category.
217     *
218     * @param category the category of the register
219     * @return the largest kind that can be stored in a register {@code category}
220     */
221    public abstract PlatformKind getLargestStorableKind(RegisterCategory category);
222
223    @Override
224    public final boolean equals(Object obj) {
225        if (obj == this) {
226            return true;
227        }
228        if (obj instanceof Architecture) {
229            Architecture that = (Architecture) obj;
230            if (this.name.equals(that.name)) {
231                assert this.byteOrder.equals(that.byteOrder);
232                assert this.implicitMemoryBarriers == that.implicitMemoryBarriers;
233                assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset;
234                assert this.registerReferenceMapSize == that.registerReferenceMapSize;
235                assert Arrays.equals(this.registers, that.registers);
236                assert this.returnAddressSize == that.returnAddressSize;
237                assert this.unalignedMemoryAccess == that.unalignedMemoryAccess;
238                assert this.wordSize == that.wordSize;
239                return true;
240            }
241        }
242        return false;
243    }
244
245    @Override
246    public final int hashCode() {
247        return name.hashCode();
248    }
249}