001/*
002 * Copyright (c) 2009, 2014, 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 jdk.internal.jvmci.meta.*;
026
027/**
028 * Represents a target machine register.
029 */
030public final class Register implements Comparable<Register> {
031
032    public static final RegisterCategory SPECIAL = new RegisterCategory("SPECIAL");
033
034    /**
035     * Invalid register.
036     */
037    public static final Register None = new Register(-1, -1, "noreg", SPECIAL);
038
039    /**
040     * Frame pointer of the current method. All spill slots and outgoing stack-based arguments are
041     * addressed relative to this register.
042     */
043    public static final Register Frame = new Register(-2, -2, "framereg", SPECIAL);
044
045    public static final Register CallerFrame = new Register(-3, -3, "callerframereg", SPECIAL);
046
047    /**
048     * The identifier for this register that is unique across all the registers in a
049     * {@link Architecture}. A valid register has {@code number > 0}.
050     */
051    public final int number;
052
053    /**
054     * The mnemonic of this register.
055     */
056    public final String name;
057
058    /**
059     * The actual encoding in a target machine instruction for this register, which may or may not
060     * be the same as {@link #number}.
061     */
062    public final int encoding;
063
064    /**
065     * The assembler calls this method to get the register's encoding.
066     */
067    public int encoding() {
068        return encoding;
069    }
070
071    /**
072     * A platform specific register category that describes which values can be stored in a
073     * register.
074     */
075    private final RegisterCategory registerCategory;
076
077    /**
078     * A platform specific register type that describes which values can be stored in a register.
079     */
080    public static class RegisterCategory {
081
082        private final String name;
083
084        private final int referenceMapOffset;
085        private final int referenceMapShift;
086
087        public RegisterCategory(String name) {
088            this(name, 0, 0);
089        }
090
091        public RegisterCategory(String name, int referenceMapOffset) {
092            this(name, referenceMapOffset, 0);
093        }
094
095        public RegisterCategory(String name, int referenceMapOffset, int referenceMapShift) {
096            this.name = name;
097            this.referenceMapOffset = referenceMapOffset;
098            this.referenceMapShift = referenceMapShift;
099        }
100
101        @Override
102        public String toString() {
103            return name;
104        }
105
106        @Override
107        public int hashCode() {
108            return 23 + name.hashCode();
109        }
110
111        @Override
112        public boolean equals(Object obj) {
113            if (obj instanceof RegisterCategory) {
114                RegisterCategory that = (RegisterCategory) obj;
115                return this.referenceMapOffset == that.referenceMapOffset && this.referenceMapShift == that.referenceMapShift && this.name.equals(that.name);
116            }
117            return false;
118        }
119    }
120
121    /**
122     * Creates a {@link Register} instance.
123     *
124     * @param number unique identifier for the register
125     * @param encoding the target machine encoding for the register
126     * @param name the mnemonic name for the register
127     * @param registerCategory the register category
128     */
129    public Register(int number, int encoding, String name, RegisterCategory registerCategory) {
130        this.number = number;
131        this.name = name;
132        this.registerCategory = registerCategory;
133        this.encoding = encoding;
134    }
135
136    public RegisterCategory getRegisterCategory() {
137        return registerCategory;
138    }
139
140    /**
141     * Get the start index of this register in the {@link ReferenceMap}.
142     */
143    public int getReferenceMapIndex() {
144        return (encoding << registerCategory.referenceMapShift) + registerCategory.referenceMapOffset;
145    }
146
147    /**
148     * Gets this register as a {@linkplain RegisterValue value} with a specified kind.
149     *
150     * @param kind the specified kind
151     * @return the {@link RegisterValue}
152     */
153    public RegisterValue asValue(LIRKind kind) {
154        return new RegisterValue(kind, this);
155    }
156
157    /**
158     * Gets this register as a {@linkplain RegisterValue value} with no particular kind.
159     *
160     * @return a {@link RegisterValue} with {@link Kind#Illegal} kind.
161     */
162    public RegisterValue asValue() {
163        return asValue(LIRKind.Illegal);
164    }
165
166    /**
167     * Determines if this is a valid register.
168     *
169     * @return {@code true} iff this register is valid
170     */
171    public boolean isValid() {
172        return number >= 0;
173    }
174
175    /**
176     * Gets the maximum register {@linkplain #number number} in a given set of registers.
177     *
178     * @param registers the set of registers to process
179     * @return the maximum register number for any register in {@code registers}
180     */
181    public static int maxRegisterNumber(Register[] registers) {
182        int max = Integer.MIN_VALUE;
183        for (Register r : registers) {
184            if (r.number > max) {
185                max = r.number;
186            }
187        }
188        return max;
189    }
190
191    /**
192     * Gets the maximum register {@linkplain #encoding encoding} in a given set of registers.
193     *
194     * @param registers the set of registers to process
195     * @return the maximum register encoding for any register in {@code registers}
196     */
197    public static int maxRegisterEncoding(Register[] registers) {
198        int max = Integer.MIN_VALUE;
199        for (Register r : registers) {
200            if (r.encoding > max) {
201                max = r.encoding;
202            }
203        }
204        return max;
205    }
206
207    @Override
208    public String toString() {
209        return name;
210    }
211
212    @Override
213    public int compareTo(Register o) {
214        if (number < o.number) {
215            return -1;
216        }
217        if (number > o.number) {
218            return 1;
219        }
220        return 0;
221    }
222
223    @Override
224    public int hashCode() {
225        return 17 + name.hashCode();
226    }
227
228    @Override
229    public boolean equals(Object obj) {
230        if (obj instanceof Register) {
231            Register other = (Register) obj;
232            if (number == other.number) {
233                assert name.equals(other.name);
234                assert encoding == other.encoding;
235                assert registerCategory.equals(other.registerCategory);
236                return true;
237            }
238        }
239        return false;
240    }
241}