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.compilers.opt.ir.ia32;
014    
015    import java.util.Enumeration;
016    import org.jikesrvm.VM;
017    import org.jikesrvm.compilers.opt.OptimizingCompilerException;
018    import org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet;
019    import org.jikesrvm.compilers.opt.ir.Register;
020    import org.jikesrvm.compilers.opt.regalloc.ia32.PhysicalRegisterConstants;
021    import org.jikesrvm.compilers.opt.util.BitSet;
022    import org.jikesrvm.compilers.opt.util.CompoundEnumerator;
023    import org.jikesrvm.compilers.opt.util.EmptyEnumerator;
024    import org.jikesrvm.compilers.opt.util.ReverseEnumerator;
025    import org.jikesrvm.ia32.ArchConstants;
026    import org.jikesrvm.ia32.RegisterConstants;
027    
028    /**
029     * This class represents a set of Registers corresponding to the
030     * IA32 register set.
031     */
032    public abstract class PhysicalRegisterSet extends GenericPhysicalRegisterSet
033        implements RegisterConstants, PhysicalRegisterConstants {
034    
035      /**
036       * This array holds a pool of objects representing physical registers
037       */
038      private final Register[] reg = new Register[getSize()];
039    
040      /**
041       * Cache the set of volatile registers for efficiency
042       */
043      private final BitSet volatileSet;
044    
045      /**
046       * Cache the set of floating-point registers for efficiency
047       */
048      private final BitSet fpSet;
049    
050      /**
051       * Return the total number of physical registers.
052       */
053      public static int getSize() {
054        return NUM_GPRS + NUM_FPRS + NUM_SPECIALS;
055      }
056    
057      /**
058       * Return the total number of physical registers.
059       */
060      public final int getNumberOfPhysicalRegisters() {
061        return getSize();
062      }
063    
064      /**
065       * Return the total number of nonvolatile GPRs.
066       */
067      public static int getNumberOfNonvolatileGPRs() {
068        return NUM_NONVOLATILE_GPRS;
069      }
070    
071      /**
072       * Return the total number of GPRs that may hold parameters.
073       */
074      public static int getNumberOfGPRParams() {
075        return NUM_PARAMETER_GPRS;
076      }
077    
078      /**
079       * Return the total number of FPRs that may hold parameters.
080       */
081      public static int getNumberOfFPRParams() {
082        return NUM_PARAMETER_FPRS;
083      }
084    
085      /**
086       * Return the (zero-based indexed) nth GPR that may hold a parameter.
087       */
088      public final Register getGPRParam(int n) {
089        if (VM.VerifyAssertions) VM._assert(n < 2);
090        if (n == 0) {
091          return getEAX();
092        } else {
093          return getEDX();
094        }
095      }
096    
097      /**
098       * Return the (zero-based indexed) nth FPR that may hold a parameter.
099       */
100      public final Register getFPRParam(int n) {
101        return getFPR(VOLATILE_FPRS[n]);
102      }
103    
104      /**
105       * Return the (zero-based indexed) nth GPR that may hold a return value.
106       */
107      public Register getReturnGPR(int n) {
108        if (VM.VerifyAssertions) VM._assert(n < 2);
109        if (n == 0) {
110          return getEAX();
111        } else {
112          return getEDX();
113        }
114      }
115    
116      /**
117       * Constructor: set up a pool of physical registers.
118       */
119      protected PhysicalRegisterSet() {
120    
121        // 1. Create all the physical registers in the pool.
122        for (int i = 0; i < reg.length; i++) {
123          Register r = new Register(i);
124          r.setPhysical();
125          reg[i] = r;
126        }
127    
128        // 2. Set the 'integer' attribute on each GPR
129        for (int i = FIRST_INT; i < FIRST_DOUBLE; i++) {
130          reg[i].setInteger();
131        }
132    
133        // 3. Set the 'double' attribute on each FPR
134        for (int i = FIRST_DOUBLE; i < FIRST_SPECIAL; i++) {
135          reg[i].setDouble();
136        }
137    
138        // 4. set up the volatile GPRs
139        for (Enumeration<Register> e = enumerateVolatileGPRs(); e.hasMoreElements();) {
140          Register r = e.nextElement();
141          r.setVolatile();
142        }
143    
144        // 5. set up the non-volatile GPRs
145        for (Enumeration<Register> e = enumerateNonvolatileGPRs(); e.hasMoreElements();) {
146          Register r = e.nextElement();
147          r.setNonVolatile();
148        }
149    
150        // 6. set properties on some special registers
151        reg[AF].setSpansBasicBlock();
152        reg[CF].setSpansBasicBlock();
153        reg[OF].setSpansBasicBlock();
154        reg[PF].setSpansBasicBlock();
155        reg[SF].setSpansBasicBlock();
156        reg[ZF].setSpansBasicBlock();
157        reg[C0].setSpansBasicBlock();
158        reg[C1].setSpansBasicBlock();
159        reg[C2].setSpansBasicBlock();
160        reg[C3].setSpansBasicBlock();
161        reg[THREAD_REGISTER.value()].setSpansBasicBlock();
162    
163        // For SSE2
164        reg[ST0].setDouble();
165        reg[ST1].setDouble();
166    
167        // 7. set up the volatile FPRs
168        for (Enumeration<Register> e = enumerateVolatileFPRs(); e.hasMoreElements();) {
169          Register r = e.nextElement();
170          r.setVolatile();
171        }
172    
173        // 8. set up the non-volatile FPRs
174        for (Enumeration<Register> e = enumerateNonvolatileFPRs(); e.hasMoreElements();) {
175          Register r = e.nextElement();
176          r.setNonVolatile();
177        }
178    
179        // 9. Cache the volatile registers for efficiency
180        volatileSet = new BitSet(this);
181        for (Enumeration<Register> e = enumerateVolatiles(); e.hasMoreElements();) {
182          Register r = e.nextElement();
183          volatileSet.add(r);
184        }
185    
186        // 10. Cache the FPRs for efficiency
187        fpSet = new BitSet(this);
188        for (Enumeration<Register> e = enumerateFPRs(); e.hasMoreElements();) {
189          Register r = e.nextElement();
190          fpSet.add(r);
191        }
192    
193        // Note no registers are excluded from live analysis (as is done for PPC)
194    
195      }
196    
197      /**
198       * Is a particular register subject to allocation?
199       */
200      public boolean isAllocatable(Register r) {
201        return (r.number < FIRST_SPECIAL && r != getTR() && r != getESP());
202      }
203    
204      /**
205       * @return the processor register
206       */
207      public Register getTR() {
208        return getGPR(THREAD_REGISTER);
209      }
210    
211      /**
212       * @return the frame pointer register
213       */
214      public Register getFP() {
215        throw new OptimizingCompilerException("Framepointer is not a register on IA32");
216      }
217    
218      /**
219       * @return the EAX register
220       */
221      public Register getEAX() {
222        return getGPR(EAX);
223      }
224    
225      /**
226       * @return the ECX register
227       */
228      public Register getECX() {
229        return getGPR(ECX);
230      }
231    
232      /**
233       * @return the EDX register
234       */
235      public Register getEDX() {
236        return getGPR(EDX);
237      }
238    
239      /**
240       * @return the EBX register
241       */
242      public Register getEBX() {
243        return getGPR(EBX);
244      }
245    
246      /**
247       * @return the ESP register
248       */
249      public Register getESP() {
250        return getGPR(ESP);
251      }
252    
253      /**
254       * @return the EBP register
255       */
256      public Register getEBP() {
257        return getGPR(EBP);
258      }
259    
260      /**
261       * @return the ESI register
262       */
263      public Register getESI() {
264        return getGPR(ESI);
265      }
266    
267      /**
268       * @return the EDI register
269       */
270      public Register getEDI() {
271        return getGPR(EDI);
272      }
273    
274      /**
275       * @return a register representing the AF bit of the EFLAGS register.
276       */
277      public Register getAF() {
278        return reg[AF];
279      }
280    
281      /**
282       * @return a register representing the CF bit of the EFLAGS register.
283       */
284      public Register getCF() {
285        return reg[CF];
286      }
287    
288      /**
289       * @return a register representing the OF bit of the EFLAGS register.
290       */
291      public Register getOF() {
292        return reg[OF];
293      }
294    
295      /**
296       * @return a register representing the PF bit of the EFLAGS register.
297       */
298      public Register getPF() {
299        return reg[PF];
300      }
301    
302      /**
303       * @return a register representing the SF bit of the EFLAGS register.
304       */
305      public Register getSF() {
306        return reg[SF];
307      }
308    
309      /**
310       * @return a register representing the ZF bit of the EFLAGS register.
311       */
312      public Register getZF() {
313        return reg[ZF];
314      }
315    
316      /**
317       * @return a register representing the C0 floating-point status bit
318       */
319      public Register getC0() {
320        return reg[C0];
321      }
322    
323      /**
324       * @return a register representing the C1 floating-point status bit
325       */
326      public Register getC1() {
327        return reg[C1];
328      }
329    
330      /**
331       * @return a register representing the C2 floating-point status bit
332       */
333      public Register getC2() {
334        return reg[C2];
335      }
336    
337      /**
338       * @return a register representing the C3 floating-point status bit
339       */
340      public Register getC3() {
341        return reg[C3];
342      }
343    
344      /**
345       * @return the nth physical GPR
346       */
347      public Register getGPR(GPR n) {
348        return reg[FIRST_INT + n.value()];
349      }
350    
351      /**
352       * @return the nth physical GPR
353       */
354      public Register getGPR(int n) {
355        return reg[FIRST_INT + n];
356      }
357    
358      /**
359       * @return the index into the GPR set corresponding to a given register.
360       *
361       * PRECONDITION: r is a physical GPR
362       */
363      public static int getGPRIndex(Register r) {
364        return r.number - FIRST_INT;
365      }
366    
367      /**
368       * @return the first GPR register used to hold a return value
369       */
370      public Register getFirstReturnGPR() {
371        if (VM.VerifyAssertions) VM._assert(NUM_RETURN_GPRS > 0);
372        return getEAX();
373      }
374    
375      /**
376       * @return the second GPR register used to hold a return value
377       */
378      public Register getSecondReturnGPR() {
379        if (VM.VerifyAssertions) VM._assert(NUM_RETURN_GPRS > 1);
380        return getEDX();
381      }
382    
383      /**
384       * @return the FPR register used to hold a return value
385       */
386      public Register getST0() {
387        if (VM.VerifyAssertions) VM._assert(NUM_RETURN_FPRS == 1);
388        if (VM.VerifyAssertions) VM._assert(ArchConstants.SSE2_FULL);
389        return reg[ST0];
390      }
391      /**
392       * @return the special ST1 x87 register
393       */
394      public Register getST1() {
395        if (VM.VerifyAssertions) VM._assert(ArchConstants.SSE2_FULL);
396        return reg[ST1];
397      }
398    
399      /**
400       * @return the FPR register used to hold a return value
401       */
402      public Register getReturnFPR() {
403        if (VM.VerifyAssertions) VM._assert(NUM_RETURN_FPRS == 1);
404        return getFPR(0);
405      }
406    
407      /**
408       * @return the nth physical FPR
409       */
410      public Register getFPR(FloatingPointMachineRegister n) {
411        return reg[FIRST_DOUBLE + n.value()];
412      }
413    
414      /**
415       * @return the nth physical FPR
416       */
417      public Register getFPR(int n) {
418        return reg[FIRST_DOUBLE + n];
419      }
420    
421      /**
422       * @return the index into the GPR set corresponding to a given register.
423       *
424       * PRECONDITION: r is a physical GPR
425       */
426      public static int getFPRIndex(Register r) {
427        return r.number - FIRST_DOUBLE;
428      }
429    
430      /**
431       * @return the nth physical register in the pool.
432       */
433      public Register get(int n) {
434        return reg[n];
435      }
436    
437      /**
438       * Given a symbolic register, return a code that gives the physical
439       * register type to hold the value of the symbolic register.
440       * @param r a symbolic register
441       * @return one of INT_REG, DOUBLE_REG
442       */
443      public static int getPhysicalRegisterType(Register r) {
444        if (r.isInteger() || r.isLong() || r.isAddress()) {
445          return INT_REG;
446        } else if (r.isFloatingPoint()) {
447          return DOUBLE_REG;
448        } else {
449          throw new OptimizingCompilerException("getPhysicalRegisterType " + " unexpected " + r);
450        }
451      }
452    
453      /**
454       * Register names for each class. used in printing the IR
455       */
456      private static final String[] registerName = new String[getSize()];
457    
458      static {
459        String[] regName = registerName;
460        for (GPR r : GPR.values()) {
461          regName[r.ordinal() + FIRST_INT] = r.toString();
462        }
463        if (ArchConstants.SSE2_FULL) {
464          for (XMM r : XMM.values()) {
465            regName[r.ordinal() + FIRST_DOUBLE] = r.toString();
466          }
467        } else {
468          for (FPR r : FPR.values()) {
469            regName[r.ordinal() + FIRST_DOUBLE] = r.toString();
470          }
471        }
472        regName[THREAD_REGISTER.value()] = "TR";
473        regName[AF] = "AF";
474        regName[CF] = "CF";
475        regName[OF] = "OF";
476        regName[PF] = "PF";
477        regName[SF] = "SF";
478        regName[ZF] = "ZF";
479        regName[ST0] = "ST0";
480        regName[ST1] = "ST1";
481      }
482    
483      /**
484       * Get the register name for a register with a particular number in the
485       * pool
486       */
487      public static String getName(int number) {
488        return registerName[number];
489      }
490    
491      /**
492       * Get the spill size for a register with a particular type
493       * @param type one of INT_REG, DOUBLE_REG, SPECIAL_REG
494       */
495      public static int getSpillSize(int type) {
496        if (VM.VerifyAssertions) {
497          VM._assert((type == INT_REG) || (type == DOUBLE_REG) || (type == SPECIAL_REG));
498        }
499        if (type == DOUBLE_REG) {
500          return 8;
501        } else {
502          return 4;
503        }
504      }
505    
506      /**
507       * Get the required spill alignment for a register with a particular type
508       * @param type one of INT_REG, DOUBLE_REG,  SPECIAL_REG
509       */
510      public static int getSpillAlignment(int type) {
511        if (VM.VerifyAssertions) {
512          VM._assert((type == INT_REG) || (type == DOUBLE_REG) || (type == SPECIAL_REG));
513        }
514        if (type == DOUBLE_REG) {
515          return 8;
516        } else {
517          return 4;
518        }
519      }
520    
521      /**
522       * Enumerate all the physical registers in this set.
523       */
524      public Enumeration<Register> enumerateAll() {
525        return new RangeEnumeration(0, getSize() - 1);
526      }
527    
528      /**
529       * Enumerate all the GPRs in this set.
530       */
531      public Enumeration<Register> enumerateGPRs() {
532        return new RangeEnumeration(FIRST_INT, FIRST_DOUBLE - 1);
533      }
534    
535      /**
536       * Enumerate all the GPRs in this set.
537       */
538      public Enumeration<Register> enumerateFPRs() {
539        return new RangeEnumeration(FIRST_DOUBLE, FIRST_SPECIAL - 1);
540      }
541    
542      /**
543       * Enumerate all the volatile GPRs in this set.
544       */
545      public PhysicalRegisterEnumeration enumerateVolatileGPRs() {
546        Register[] r = new Register[NUM_VOLATILE_GPRS];
547        for (int i = 0; i < NUM_VOLATILE_GPRS; i++) {
548          r[i] = getGPR(VOLATILE_GPRS[i]);
549        }
550        return new PhysicalRegisterEnumeration(r);
551      }
552    
553      /**
554       * Enumerate all the nonvolatile GPRs in this set.
555       */
556      public PhysicalRegisterEnumeration enumerateNonvolatileGPRs() {
557        Register[] r = new Register[NUM_NONVOLATILE_GPRS];
558        for (int i = 0; i < NUM_NONVOLATILE_GPRS; i++) {
559          r[i] = getGPR(NONVOLATILE_GPRS[i]);
560        }
561        return new PhysicalRegisterEnumeration(r);
562      }
563    
564      /**
565       * Enumerate the nonvolatile GPRS backwards
566       */
567      public Enumeration<Register> enumerateNonvolatileGPRsBackwards() {
568        return new ReverseEnumerator<Register>(enumerateNonvolatileGPRs());
569      }
570    
571      /**
572       * Enumerate all the volatile FPRs in this set.
573       */
574      public PhysicalRegisterEnumeration enumerateVolatileFPRs() {
575        Register[] r = new Register[NUM_VOLATILE_FPRS];
576        for (int i = 0; i < NUM_VOLATILE_FPRS; i++) {
577          r[i] = getFPR(VOLATILE_FPRS[i]);
578        }
579        return new PhysicalRegisterEnumeration(r);
580      }
581    
582      /**
583       * Enumerate all the nonvolatile FPRs in this set.
584       */
585      public PhysicalRegisterEnumeration enumerateNonvolatileFPRs() {
586        Register[] r = new Register[NUM_NONVOLATILE_FPRS];
587        for (int i = 0; i < NUM_NONVOLATILE_FPRS; i++) {
588          r[i] = getFPR(NONVOLATILE_FPRS[i]);
589        }
590        return new PhysicalRegisterEnumeration(r);
591      }
592    
593      /**
594       * Enumerate the volatile physical registers of a given class.
595       * @param regClass one of INT_REG, DOUBLE_REG, SPECIAL_REG
596       */
597      public Enumeration<Register> enumerateVolatiles(int regClass) {
598        switch (regClass) {
599          case INT_REG:
600            return enumerateVolatileGPRs();
601          case DOUBLE_REG:
602            return enumerateVolatileFPRs();
603          case SPECIAL_REG:
604            return EmptyEnumerator.emptyEnumeration();
605          default:
606            throw new OptimizingCompilerException("Unsupported volatile type");
607        }
608      }
609    
610      /**
611       * Enumerate all the volatile physical registers
612       */
613      public Enumeration<Register> enumerateVolatiles() {
614        Enumeration<Register> e1 = enumerateVolatileGPRs();
615        Enumeration<Register> e2 = enumerateVolatileFPRs();
616        return new CompoundEnumerator<Register>(e1, e2);
617      }
618    
619      /**
620       * @return the set of volatile physical registers
621       */
622      public BitSet getVolatiles() {
623        return volatileSet;
624      }
625    
626      /**
627       * @return the set of FPR physical registers
628       */
629      public BitSet getFPRs() {
630        return fpSet;
631      }
632    
633      /**
634       * Enumerate the nonvolatile physical registers of a given class.
635       * @param regClass one of INT_REG, DOUBLE_REG, SPECIAL_REG
636       */
637      public Enumeration<Register> enumerateNonvolatiles(int regClass) {
638        switch (regClass) {
639          case INT_REG:
640            return enumerateNonvolatileGPRs();
641          case DOUBLE_REG:
642            return enumerateNonvolatileFPRs();
643          case SPECIAL_REG:
644            return EmptyEnumerator.emptyEnumeration();
645          default:
646            throw new OptimizingCompilerException("Unsupported non-volatile type");
647        }
648      }
649    
650      /**
651       * Enumerate the nonvolatile physical registers of a given class,
652       * backwards
653       * @param regClass one of INT_REG, DOUBLE_REG, SPECIAL_REG
654       */
655      public Enumeration<Register> enumerateNonvolatilesBackwards(int regClass) {
656        return new ReverseEnumerator<Register>(enumerateNonvolatiles(regClass));
657      }
658    
659      /**
660       * An enumerator for use by the physical register utilities.
661       */
662      static final class PhysicalRegisterEnumeration implements Enumeration<Register> {
663        private int index;
664        private final Register[] r;
665    
666        PhysicalRegisterEnumeration(Register[] r) {
667          this.r = r;
668          this.index = 0;
669        }
670    
671        public Register nextElement() {
672          return r[index++];
673        }
674    
675        public boolean hasMoreElements() {
676          return (index < r.length);
677        }
678      }
679    
680      /**
681       * An enumerator for use by the physical register utilities.
682       */
683      final class RangeEnumeration implements Enumeration<Register> {
684        private final int end;
685        private int index;
686        private final int exclude; // an index in the register range to exclude
687    
688        RangeEnumeration(int start, int end) {
689          this.end = end;
690          this.exclude = -1;
691          this.index = start;
692        }
693    
694        RangeEnumeration(int start, int end, int exclude) {
695          this.end = end;
696          this.exclude = exclude;
697          this.index = start;
698        }
699    
700        public Register nextElement() {
701          if (index == exclude) index++;
702          return reg[index++];
703        }
704    
705        public boolean hasMoreElements() {
706          if (index == exclude) index++;
707          return (index <= end);
708        }
709      }
710    }