1 /*
2  * Copyright (c) 2009, 2016, 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 jdk.vm.ci.meta.ValueKind;
26 
27 /**
28  * Represents a target machine register.
29  */
30 public final class Register implements Comparable<Register> {
31 
32     public static final RegisterCategory SPECIAL = new RegisterCategory("SPECIAL");
33 
34     /**
35      * Invalid register.
36      */
37     public static final Register None = new Register(-1, -1, "noreg", SPECIAL);
38 
39     /**
40      * The identifier for this register that is unique across all the registers in a
41      * {@link Architecture}. A valid register has {@code number >= 0}.
42      */
43     public final int number;
44 
45     /**
46      * The mnemonic of this register.
47      */
48     public final String name;
49 
50     /**
51      * The actual encoding in a target machine instruction for this register, which may or may not
52      * be the same as {@link #number}.
53      */
54     public final int encoding;
55 
56     /**
57      * The assembler calls this method to get the register's encoding.
58      */
encoding()59     public int encoding() {
60         return encoding;
61     }
62 
63     /**
64      * A platform specific register category that describes which values can be stored in a
65      * register.
66      */
67     private final RegisterCategory registerCategory;
68 
69     /**
70      * A platform specific register type that describes which values can be stored in a register.
71      */
72     public static class RegisterCategory {
73 
74         private final String name;
75         private final boolean mayContainReference;
76 
RegisterCategory(String name)77         public RegisterCategory(String name) {
78             this(name, true);
79         }
80 
RegisterCategory(String name, boolean mayContainReference)81         public RegisterCategory(String name, boolean mayContainReference) {
82             this.name = name;
83             this.mayContainReference = mayContainReference;
84         }
85 
86         @Override
toString()87         public String toString() {
88             return name;
89         }
90 
91         @Override
hashCode()92         public int hashCode() {
93             return 23 + name.hashCode();
94         }
95 
96         @Override
equals(Object obj)97         public boolean equals(Object obj) {
98             if (obj instanceof RegisterCategory) {
99                 RegisterCategory that = (RegisterCategory) obj;
100                 return this.name.equals(that.name);
101             }
102             return false;
103         }
104     }
105 
106     /**
107      * Creates a {@link Register} instance.
108      *
109      * @param number unique identifier for the register
110      * @param encoding the target machine encoding for the register
111      * @param name the mnemonic name for the register
112      * @param registerCategory the register category
113      */
Register(int number, int encoding, String name, RegisterCategory registerCategory)114     public Register(int number, int encoding, String name, RegisterCategory registerCategory) {
115         this.number = number;
116         this.name = name;
117         this.registerCategory = registerCategory;
118         this.encoding = encoding;
119     }
120 
getRegisterCategory()121     public RegisterCategory getRegisterCategory() {
122         return registerCategory;
123     }
124 
125     /**
126      * Determine whether this register needs to be part of the reference map.
127      */
mayContainReference()128     public boolean mayContainReference() {
129         return registerCategory.mayContainReference;
130     }
131 
132     /**
133      * Gets this register as a {@linkplain RegisterValue value} with a specified kind.
134      *
135      * @param kind the specified kind
136      * @return the {@link RegisterValue}
137      */
asValue(ValueKind<?> kind)138     public RegisterValue asValue(ValueKind<?> kind) {
139         return new RegisterValue(kind, this);
140     }
141 
142     /**
143      * Gets this register as a {@linkplain RegisterValue value} with no particular kind.
144      *
145      * @return a {@link RegisterValue} with {@link ValueKind#Illegal} kind.
146      */
asValue()147     public RegisterValue asValue() {
148         return asValue(ValueKind.Illegal);
149     }
150 
151     /**
152      * Determines if this is a valid register.
153      *
154      * @return {@code true} iff this register is valid
155      */
isValid()156     public boolean isValid() {
157         return number >= 0;
158     }
159 
160     @Override
toString()161     public String toString() {
162         return name;
163     }
164 
165     @Override
compareTo(Register o)166     public int compareTo(Register o) {
167         if (number < o.number) {
168             return -1;
169         }
170         if (number > o.number) {
171             return 1;
172         }
173         return 0;
174     }
175 
176     @Override
hashCode()177     public int hashCode() {
178         return 17 + name.hashCode();
179     }
180 
181     @Override
equals(Object obj)182     public boolean equals(Object obj) {
183         if (obj instanceof Register) {
184             Register other = (Register) obj;
185             if (number == other.number) {
186                 assert name.equals(other.name);
187                 assert encoding == other.encoding;
188                 assert registerCategory.equals(other.registerCategory);
189                 return true;
190             }
191         }
192         return false;
193     }
194 }
195