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