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