001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.ia32;
014
015import static org.jikesrvm.util.Bits.*;
016
017import org.vmmagic.pragma.Pure;
018import org.vmmagic.pragma.UninterruptibleNoWarn;
019import org.jikesrvm.VM;
020import org.jikesrvm.architecture.MachineRegister;
021import org.jikesrvm.runtime.Magic;
022
023public final class RegisterConstants {
024  //---------------------------------------------------------------------------------------//
025  //               RVM register usage conventions - Intel version.                         //
026  //---------------------------------------------------------------------------------------//
027
028  /** log2 of instruction width in bytes */
029  public static final byte LG_INSTRUCTION_WIDTH = 0;
030  public static final int INSTRUCTION_WIDTH = 1 << LG_INSTRUCTION_WIDTH;
031
032  /**
033   * Common interface implemented by all registers constants
034   */
035  public interface IntelMachineRegister extends MachineRegister {
036    byte value();
037    /** @return does this register require a REX prefix byte? */
038    boolean needsREXprefix();
039  }
040
041  /**
042   * Super interface for floating point registers
043   */
044  public interface FloatingPointMachineRegister extends IntelMachineRegister {
045  }
046
047  /**
048   * Representation of general purpose registers
049   */
050  public enum GPR implements IntelMachineRegister {
051    EAX(0), ECX(1), EDX(2), EBX(3), ESP(4), EBP(5), ESI(6), EDI(7),
052    R8(8), R9(9), R10(10), R11(11), R12(12), R13(13), R14(14), R15(15),
053    EIP(16);
054
055    /** Local copy of the backing array. Copied here to avoid calls to clone */
056    private static final GPR[] vals = values();
057
058    GPR(int v) {
059      if (v != ordinal()) {
060        throw new Error("Invalid register ordinal");
061      }
062    }
063    @Override
064    @UninterruptibleNoWarn("Interruptible code only called during boot image creation")
065    @Pure
066    public byte value() {
067      byte result;
068      if (!org.jikesrvm.VM.runningVM) {
069        result = (byte)ordinal();
070      } else {
071        result = (byte)java.lang.JikesRVMSupport.getEnumOrdinal(this);
072      }
073      if (VM.VerifyAssertions) {
074        if (VM.buildFor32Addr()) {
075          VM._assert(result >= 0 && result <= 7);
076        } else {
077          VM._assert(result >= 0 && result <= 15);
078        }
079      }
080      return result;
081    }
082    /** @return encoded value of this register to be included in the opcode byte */
083    @Pure
084    public byte valueForOpcode() {
085      byte result;
086      if (!org.jikesrvm.VM.runningVM) {
087        result = (byte)ordinal();
088      } else {
089        result = (byte)java.lang.JikesRVMSupport.getEnumOrdinal(this);
090      }
091      if (!VM.buildFor32Addr()) {
092        result &= 0x7;
093      }
094      if (VM.VerifyAssertions) {
095        VM._assert(result >= 0 && result <= 7);
096      }
097      return result;
098    }
099    @Override
100    @Pure
101    public boolean needsREXprefix() {
102      if (VM.buildFor32Addr()) {
103        return false;
104      } else {
105        return (this != EIP) && (value() > 7);
106      }
107    }
108    /**
109     * Intel have two flavours of 8bit opcodes, ones that operate on 32bit
110     * registers and ones that operate on 8bit registers. As the high half of
111     * 8bit registers doesn't allow ESI, EDI, EBP, ESP to be encoded, this
112     * routine returns true if this register is one of those unencodable
113     * registers.
114     * @return can this register be encoded as an 8byte register?
115     */
116    @Pure
117    public boolean isValidAs8bitRegister() {
118      byte v = value();
119      return (v < 4) || (!VM.buildFor32Addr() && v > 7);
120    }
121    /**
122     * Convert encoded value into the GPR it represents
123     * @param num encoded value
124     * @return represented GPR
125     */
126    @Pure
127    public static GPR lookup(int num) {
128      return vals[num];
129    }
130    /**
131     * Convert encoded value representing an opcode into the GPR to represent it
132     * @param opcode encoded value
133     * @return represented GPR
134     */
135    public static GPR getForOpcode(int opcode) {
136      if (VM.VerifyAssertions) VM._assert(opcode >= 0 && opcode <= 7);
137      return lookup(opcode);
138    }
139  }
140
141  /**
142   * Representation of x87 floating point registers
143   */
144  public enum FPR implements FloatingPointMachineRegister {
145    FP0(0), FP1(1), FP2(2), FP3(3), FP4(4), FP5(5), FP6(6), FP7(7);
146    /** Local copy of the backing array. Copied here to avoid calls to clone */
147    private static final FPR[] vals = values();
148
149    FPR(int v) {
150      if (v != ordinal()) {
151        throw new Error("Invalid register ordinal");
152      }
153    }
154    @Override
155    @Pure
156    public byte value() {
157      return (byte)ordinal();
158    }
159    @Override
160    @Pure
161    public boolean needsREXprefix() {
162      return false; // do REX prefixes of floating point operands make sense?
163    }
164    /**
165     * Convert encoded value into the FPR it represents
166     * @param num encoded value
167     * @return represented FPR
168     */
169    @Pure
170    public static FPR lookup(int num) {
171      return vals[num];
172    }
173  }
174  /**
175   * Representation of MMX MM registers
176   * N.B. MM and x87 FPR registers alias
177   */
178  public enum MM implements IntelMachineRegister {
179    MM0(0), MM1(1), MM2(2), MM3(3), MM4(4), MM5(5), MM6(6), MM7(7),
180    MM8(8), MM9(9), MM10(10), MM11(11), MM12(12), MM13(13), MM14(14), MM15(15);
181    /** Local copy of the backing array. Copied here to avoid calls to clone */
182    private static final MM[] vals = values();
183
184    MM(int v) {
185      if (v != ordinal()) {
186        throw new Error("Invalid register ordinal");
187      }
188    }
189    @Override
190    @Pure
191    public byte value() {
192      return (byte)ordinal();
193    }
194    @Override
195    @Pure
196    public boolean needsREXprefix() {
197      if (VM.buildFor32Addr()) {
198        return false;
199      } else {
200        return value() > 7;
201      }
202    }
203    /**
204     * Convert encoded value into the MM it represents
205     * @param num encoded value
206     * @return represented MM
207     */
208    @Pure
209    public static MM lookup(int num) {
210      return vals[num];
211    }
212  }
213
214  /**
215   * Representation of SSE XMM registers
216   */
217  public enum XMM implements FloatingPointMachineRegister {
218    XMM0(0), XMM1(1), XMM2(2), XMM3(3), XMM4(4), XMM5(5), XMM6(6), XMM7(7),
219    XMM8(8), XMM9(9), XMM10(10), XMM11(11), XMM12(12), XMM13(13), XMM14(14), XMM15(15);
220    /** Local copy of the backing array. Copied here to avoid calls to clone */
221    private static final XMM[] vals = values();
222
223    XMM(int v) {
224      if (v != ordinal()) {
225        throw new Error("Invalid register ordinal");
226      }
227    }
228    @Override
229    @Pure
230    public byte value() {
231      return (byte)ordinal();
232    }
233    @Override
234    @Pure
235    public boolean needsREXprefix() {
236      if (VM.buildFor32Addr()) {
237        return false;
238      } else {
239        return value() > 7;
240      }
241    }
242    /**
243     * Convert encoded value into the XMM it represents
244     * @param num encoded value
245     * @return represented XMM
246     */
247    @Pure
248    public static XMM lookup(int num) {
249      return vals[num];
250    }
251  }
252
253  /*
254   * Symbolic values for general purpose registers.
255   * These values are used to assemble instructions and as indices into:
256   *   Registers.gprs[]
257   *   Registers.fprs[]
258   *   GCMapIterator.registerLocations[]
259   *   RegisterConstants.GPR_NAMES[]
260   */
261  public static final GPR EAX = GPR.EAX;
262  public static final GPR ECX = GPR.ECX;
263  public static final GPR EDX = GPR.EDX;
264  public static final GPR EBX = GPR.EBX;
265  public static final GPR ESP = GPR.ESP;
266  public static final GPR EBP = GPR.EBP;
267  public static final GPR ESI = GPR.ESI;
268  public static final GPR EDI = GPR.EDI;
269
270  public static final GPR R0 = GPR.EAX;
271  public static final GPR R1 = GPR.ECX;
272  public static final GPR R2 = GPR.EDX;
273  public static final GPR R3 = GPR.EBX;
274  public static final GPR R4 = GPR.ESP;
275  public static final GPR R5 = GPR.EBP;
276  public static final GPR R6 = GPR.ESI;
277  public static final GPR R7 = GPR.EDI;
278  public static final GPR R8 = GPR.R8;
279  public static final GPR R9 = GPR.R9;
280  public static final GPR R10 = GPR.R10;
281  public static final GPR R11 = GPR.R11;
282  public static final GPR R12 = GPR.R12;
283  public static final GPR R13 = GPR.R13;
284  public static final GPR R14 = GPR.R14;
285  public static final GPR R15 = GPR.R15;
286
287  public static final FPR FP0 = FPR.FP0;
288  public static final FPR FP1 = FPR.FP1;
289  public static final FPR FP2 = FPR.FP2;
290  public static final FPR FP3 = FPR.FP3;
291  public static final FPR FP4 = FPR.FP4;
292  public static final FPR FP5 = FPR.FP5;
293  public static final FPR FP6 = FPR.FP6;
294  public static final FPR FP7 = FPR.FP7;
295
296  public static final MM MM0 = MM.MM0;
297  public static final MM MM1 = MM.MM1;
298  public static final MM MM2 = MM.MM2;
299  public static final MM MM3 = MM.MM3;
300  public static final MM MM4 = MM.MM4;
301  public static final MM MM5 = MM.MM5;
302  public static final MM MM6 = MM.MM6;
303  public static final MM MM7 = MM.MM7;
304  public static final MM MM8 = MM.MM8;
305  public static final MM MM9 = MM.MM9;
306  public static final MM MM10 = MM.MM10;
307  public static final MM MM11 = MM.MM11;
308  public static final MM MM12 = MM.MM12;
309  public static final MM MM13 = MM.MM13;
310  public static final MM MM14 = MM.MM14;
311  public static final MM MM15 = MM.MM15;
312
313  public static final XMM XMM0 = XMM.XMM0;
314  public static final XMM XMM1 = XMM.XMM1;
315  public static final XMM XMM2 = XMM.XMM2;
316  public static final XMM XMM3 = XMM.XMM3;
317  public static final XMM XMM4 = XMM.XMM4;
318  public static final XMM XMM5 = XMM.XMM5;
319  public static final XMM XMM6 = XMM.XMM6;
320  public static final XMM XMM7 = XMM.XMM7;
321  public static final XMM XMM8 = XMM.XMM8;
322  public static final XMM XMM9 = XMM.XMM9;
323  public static final XMM XMM10 = XMM.XMM10;
324  public static final XMM XMM11 = XMM.XMM11;
325  public static final XMM XMM12 = XMM.XMM12;
326  public static final XMM XMM13 = XMM.XMM13;
327  public static final XMM XMM14 = XMM.XMM14;
328  public static final XMM XMM15 = XMM.XMM15;
329
330  /*
331   * Dedicated registers.
332   */
333
334  /** Register current stack pointer. NB the frame pointer is maintained in the processor. */
335  public static final GPR STACK_POINTER = ESP;
336  /** Register holding a reference to thread local information */
337  public static final GPR THREAD_REGISTER = ESI;
338  /** Register holding the value of the JTOC, only necessary when we can't directly address the JTOC */
339  public static final GPR JTOC_REGISTER = (VM.buildFor32Addr() || VM.runningTool ||
340      fits(Magic.getTocPointer(), 32)) ? null : R15;
341
342  /*
343   * Register sets
344   * (``range'' is a misnomer for the alphabet soup of of intel registers)
345   */
346// CHECKSTYLE:OFF
347  /** All general purpose registers */
348  public static final GPR[] ALL_GPRS =
349    VM.buildFor32Addr() ? new GPR[]{EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI}
350                        : new GPR[]{EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, R8, R9, R10, R11, R12, R13, R14, R15};
351
352  /** Number of general purpose registers */
353  public static final byte NUM_GPRS = (byte)ALL_GPRS.length;
354
355  /**
356   * All floating point purpose registers
357   * NB with SSE x87 registers must be explicitly managed
358   */
359  public static final FloatingPointMachineRegister[] ALL_FPRS =
360    VM.buildFor32Addr() ? (VM.buildForSSE2() ? new FPR[]{FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7}
361                                             : new XMM[]{XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7})
362      : new XMM[]{XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
363                  XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15};
364
365  /** Number of floating point registers */
366  public static final byte NUM_FPRS = (byte)ALL_FPRS.length;
367
368  /**
369   * Volatile general purpose registers.
370   * NB: the order here is important.  The opt-compiler allocates
371   * the volatile registers in the order they appear here.
372   */
373  public static final GPR[] VOLATILE_GPRS = VM.buildFor32Addr() ? new GPR[]{R0 /*EAX*/, R2 /*EDX*/, R1 /*ECX*/} : new GPR[]{R0, R2, R1};
374  public static final int NUM_VOLATILE_GPRS = VOLATILE_GPRS.length;
375
376  /**
377   * Volatile floating point registers within the RVM.
378   * TODO: this should include XMMs
379   */
380  public static final FloatingPointMachineRegister[] VOLATILE_FPRS = {FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7};
381  /** Number of volatile FPRs */
382  public static final int NUM_VOLATILE_FPRS = VOLATILE_FPRS.length;
383
384  /**
385   * Non-volatile general purpose registers within the RVM.
386   * Note: the order here is very important.  The opt-compiler allocates
387   * the nonvolatile registers in the reverse of order they appear here.
388   * R3 (EBX) must be last, because it is the only non-volatile that can
389   * be used in instructions that are using r8 and we must ensure that
390   * opt doesn't skip over another nonvol while looking for an r8 nonvol.
391   */
392  public static final GPR[] NONVOLATILE_GPRS =
393    VM.buildFor32Addr() ? new GPR[]{R5 /*EBP*/, R7 /*EDI*/, R3 /*EBX*/}
394                        : new GPR[]{R5, R7, R3};
395  /** Number of non-volatile GPRs */
396  public static final int NUM_NONVOLATILE_GPRS = NONVOLATILE_GPRS.length;
397
398  /** Non-volatile floating point registers within the RVM. */
399  public static final FloatingPointMachineRegister[] NONVOLATILE_FPRS = {};
400  /** Number of non-volatile FPRs */
401  public static final int NUM_NONVOLATILE_FPRS = NONVOLATILE_FPRS.length;
402
403  /** General purpose registers to pass arguments within the RVM */
404  public static final GPR[] PARAMETER_GPRS = new GPR[]{EAX, EDX};
405  /** Number of parameter GPRs */
406  public static final int NUM_PARAMETER_GPRS = PARAMETER_GPRS.length;
407
408  /** Floating point registers to pass arguments within the RVM */
409  public static final FloatingPointMachineRegister[] PARAMETER_FPRS =
410    VM.buildForSSE2() ? new XMM[]{XMM0, XMM1, XMM2, XMM3}
411                    : new FPR[]{FP0, FP1, FP2, FP3};
412  /** Number of parameter FPRs */
413    public static final int NUM_PARAMETER_FPRS = PARAMETER_FPRS.length;
414  /** GPR registers used for returning values */
415  public static final GPR[] RETURN_GPRS = VM.buildFor32Addr() ? new GPR[]{EAX, EDX} : new GPR[]{EAX};
416  /** Number of return GPRs */
417  public static final int NUM_RETURN_GPRS = RETURN_GPRS.length;
418
419  /** FPR registers used for returning values */
420  public static final FloatingPointMachineRegister[] RETURN_FPRS =
421    VM.buildForSSE2() ? new XMM[]{XMM0} : new FPR[]{FP0};
422  /** Number of return FPRs */
423  public static final int NUM_RETURN_FPRS = RETURN_FPRS.length;
424
425  /** Native volatile GPRS */
426  public static final GPR[] NATIVE_VOLATILE_GPRS = VM.buildFor32Addr() ? new GPR[]{EAX, ECX, EDX} : new GPR[]{EAX, ECX, EDX, R8, R9, R10, R11};
427  /** Native non-volatile GPRS */
428  public static final GPR[] NATIVE_NONVOLATILE_GPRS = VM.buildFor32Addr() ? new GPR[]{EBX, EBP, EDI, ESI} : new GPR[]{EBX, EBP, R12, R13, R14, R15};
429
430  /** Native volatile FPRS */
431  public static final FloatingPointMachineRegister[] NATIVE_VOLATILE_FPRS = ALL_FPRS;
432  /** Native non-volatile FPRS */
433  public static final FloatingPointMachineRegister[] NATIVE_NONVOLATILE_FPRS = new FloatingPointMachineRegister[0];
434
435  /** General purpose registers to pass arguments to native code */
436  public static final GPR[] NATIVE_PARAMETER_GPRS =
437    VM.buildFor32Addr() ? new GPR[0]
438                        : new GPR[]{EDI /*R7*/, ESI /*R6*/, EDX /*R2*/, ECX /*R1*/, R8, R9};
439
440  /** Floating point registers to pass arguments to native code */
441  public static final FloatingPointMachineRegister[] NATIVE_PARAMETER_FPRS =
442    VM.buildFor32Addr() ? new FloatingPointMachineRegister[0]
443                        : new XMM[]{XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7};
444  /** Number of native,sys parameter FPRs */
445  public static final int NUM_NATIVE_PARAMETER_FPRS = NATIVE_PARAMETER_FPRS.length;
446  /** Number of native, sys parameter GPRs */
447  public static final int NUM_NATIVE_PARAMETER_GPRS = NATIVE_PARAMETER_GPRS.length;
448// CHECKSTYLE:ON
449
450  private RegisterConstants() {
451    // prevent instantiation
452  }
453
454}