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  */
23 package jdk.vm.ci.code;
24 
25 import java.nio.ByteOrder;
26 
27 import jdk.vm.ci.code.Register.RegisterCategory;
28 import jdk.vm.ci.meta.JavaKind;
29 import 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  */
35 public 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 
Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, RegisterArray registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset, int returnAddressSize)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
toString()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      */
getWordSize()107     public int getWordSize() {
108         return wordKind.getSizeInBytes();
109     }
110 
getWordKind()111     public PlatformKind getWordKind() {
112         return wordKind;
113     }
114 
115     /**
116      * Gets the name of this architecture.
117      */
getName()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      */
getRegisters()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      */
getAvailableValueRegisters()136     public RegisterArray getAvailableValueRegisters() {
137         return getRegisters();
138     }
139 
getByteOrder()140     public ByteOrder getByteOrder() {
141         return byteOrder;
142     }
143 
144     /**
145      * @return true if the architecture supports unaligned memory accesses.
146      */
supportsUnalignedMemoryAccess()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      */
getReturnAddressSize()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      */
getMachineCodeCallDisplacementOffset()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      */
requiredBarriers(int barriers)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      */
canStoreValue(RegisterCategory category, PlatformKind kind)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      */
getLargestStorableKind(RegisterCategory category)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      */
getPlatformKind(JavaKind javaKind)196     public abstract PlatformKind getPlatformKind(JavaKind javaKind);
197 
198     @Override
equals(Object obj)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
hashCode()220     public final int hashCode() {
221         return name.hashCode();
222     }
223 }
224