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.ReverseEnumerator;
024    import org.jikesrvm.ia32.ArchConstants;
025    import org.jikesrvm.ia32.RegisterConstants;
026    import org.jikesrvm.util.EmptyEnumeration;
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      @Override
058      public final int getNumberOfPhysicalRegisters() {
059        return getSize();
060      }
061    
062      /**
063       * Return the total number of nonvolatile GPRs.
064       */
065      public static int getNumberOfNonvolatileGPRs() {
066        return NUM_NONVOLATILE_GPRS;
067      }
068    
069      /**
070       * Return the total number of GPRs that may hold parameters.
071       */
072      public static int getNumberOfGPRParams() {
073        return NUM_PARAMETER_GPRS;
074      }
075    
076      /**
077       * Return the total number of FPRs that may hold parameters.
078       */
079      public static int getNumberOfFPRParams() {
080        return NUM_PARAMETER_FPRS;
081      }
082    
083      /**
084       * Return the (zero-based indexed) nth GPR that may hold a parameter.
085       */
086      public final Register getGPRParam(int n) {
087        if (VM.VerifyAssertions) VM._assert(n < 2);
088        if (n == 0) {
089          return getEAX();
090        } else {
091          return getEDX();
092        }
093      }
094    
095      /**
096       * Return the (zero-based indexed) nth FPR that may hold a parameter.
097       */
098      public final Register getFPRParam(int n) {
099        return getFPR(VOLATILE_FPRS[n]);
100      }
101    
102      /**
103       * Return the (zero-based indexed) nth GPR that may hold a return value.
104       */
105      public Register getReturnGPR(int n) {
106        if (VM.VerifyAssertions) VM._assert(n < 2);
107        if (n == 0) {
108          return getEAX();
109        } else {
110          return getEDX();
111        }
112      }
113    
114      /**
115       * Constructor: set up a pool of physical registers.
116       */
117      protected PhysicalRegisterSet() {
118    
119        // 1. Create all the physical registers in the pool.
120        for (int i = 0; i < reg.length; i++) {
121          Register r = new Register(i);
122          r.setPhysical();
123          reg[i] = r;
124        }
125    
126        // 2. Set the 'integer' attribute on each GPR
127        for (int i = FIRST_INT; i < FIRST_DOUBLE; i++) {
128          reg[i].setInteger();
129        }
130    
131        // 3. Set the 'double' attribute on each FPR
132        for (int i = FIRST_DOUBLE; i < FIRST_SPECIAL; i++) {
133          reg[i].setDouble();
134        }
135    
136        // 4. set up the volatile GPRs
137        for (Enumeration<Register> e = enumerateVolatileGPRs(); e.hasMoreElements();) {
138          Register r = e.nextElement();
139          r.setVolatile();
140        }
141    
142        // 5. set up the non-volatile GPRs
143        for (Enumeration<Register> e = enumerateNonvolatileGPRs(); e.hasMoreElements();) {
144          Register r = e.nextElement();
145          r.setNonVolatile();
146        }
147    
148        // 6. set properties on some special registers
149        reg[AF].setSpansBasicBlock();
150        reg[CF].setSpansBasicBlock();
151        reg[OF].setSpansBasicBlock();
152        reg[PF].setSpansBasicBlock();
153        reg[SF].setSpansBasicBlock();
154        reg[ZF].setSpansBasicBlock();
155        reg[C0].setSpansBasicBlock();
156        reg[C1].setSpansBasicBlock();
157        reg[C2].setSpansBasicBlock();
158        reg[C3].setSpansBasicBlock();
159        reg[THREAD_REGISTER.value()].setSpansBasicBlock();
160    
161        // For SSE2
162        reg[ST0].setDouble();
163        reg[ST1].setDouble();
164    
165        // 7. set up the volatile FPRs
166        for (Enumeration<Register> e = enumerateVolatileFPRs(); e.hasMoreElements();) {
167          Register r = e.nextElement();
168          r.setVolatile();
169        }
170    
171        // 8. set up the non-volatile FPRs
172        for (Enumeration<Register> e = enumerateNonvolatileFPRs(); e.hasMoreElements();) {
173          Register r = e.nextElement();
174          r.setNonVolatile();
175        }
176    
177        // 9. Cache the volatile registers for efficiency
178        volatileSet = new BitSet(this);
179        for (Enumeration<Register> e = enumerateVolatiles(); e.hasMoreElements();) {
180          Register r = e.nextElement();
181          volatileSet.add(r);
182        }
183    
184        // 10. Cache the FPRs for efficiency
185        fpSet = new BitSet(this);
186        for (Enumeration<Register> e = enumerateFPRs(); e.hasMoreElements();) {
187          Register r = e.nextElement();
188          fpSet.add(r);
189        }
190    
191        // Note no registers are excluded from live analysis (as is done for PPC)
192    
193      }
194    
195      /**
196       * Is a particular register subject to allocation?
197       */
198      public boolean isAllocatable(Register r) {
199        return (r.number < FIRST_SPECIAL && r != getTR() && r != getESP());
200      }
201    
202      /**
203       * @return the processor register
204       */
205      @Override
206      public Register getTR() {
207        return getGPR(THREAD_REGISTER);
208      }
209    
210      /**
211       * @return the frame pointer register
212       */
213      @Override
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      @Override
352      public Register getGPR(int n) {
353        return reg[FIRST_INT + n];
354      }
355    
356      /**
357       * @return the index into the GPR set corresponding to a given register.
358       *
359       * PRECONDITION: r is a physical GPR
360       */
361      public static int getGPRIndex(Register r) {
362        return r.number - FIRST_INT;
363      }
364    
365      /**
366       * @return the first GPR register used to hold a return value
367       */
368      @Override
369      public Register getFirstReturnGPR() {
370        if (VM.VerifyAssertions) VM._assert(NUM_RETURN_GPRS > 0);
371        return getEAX();
372      }
373    
374      /**
375       * @return the second GPR register used to hold a return value
376       */
377      public Register getSecondReturnGPR() {
378        if (VM.VerifyAssertions) VM._assert(NUM_RETURN_GPRS > 1);
379        return getEDX();
380      }
381    
382      /**
383       * @return the FPR register used to hold a return value
384       */
385      public Register getST0() {
386        if (VM.VerifyAssertions) VM._assert(NUM_RETURN_FPRS == 1);
387        if (VM.VerifyAssertions) VM._assert(ArchConstants.SSE2_FULL);
388        return reg[ST0];
389      }
390      /**
391       * @return the special ST1 x87 register
392       */
393      public Register getST1() {
394        if (VM.VerifyAssertions) VM._assert(ArchConstants.SSE2_FULL);
395        return reg[ST1];
396      }
397    
398      /**
399       * @return the FPR register used to hold a return value
400       */
401      public Register getReturnFPR() {
402        if (VM.VerifyAssertions) VM._assert(NUM_RETURN_FPRS == 1);
403        return getFPR(0);
404      }
405    
406      /**
407       * @return the nth physical FPR
408       */
409      public Register getFPR(FloatingPointMachineRegister n) {
410        return reg[FIRST_DOUBLE + n.value()];
411      }
412    
413      @Override
414      public Register getFPR(int n) {
415        return reg[FIRST_DOUBLE + n];
416      }
417    
418      /**
419       * @return the index into the GPR set corresponding to a given register.
420       *
421       * PRECONDITION: r is a physical GPR
422       */
423      public static int getFPRIndex(Register r) {
424        return r.number - FIRST_DOUBLE;
425      }
426    
427      @Override
428      public Register get(int n) {
429        return reg[n];
430      }
431    
432      /**
433       * Given a symbolic register, return a code that gives the physical
434       * register type to hold the value of the symbolic register.
435       * @param r a symbolic register
436       * @return one of INT_REG, DOUBLE_REG
437       */
438      public static int getPhysicalRegisterType(Register r) {
439        if (r.isInteger() || r.isLong() || r.isAddress()) {
440          return INT_REG;
441        } else if (r.isFloatingPoint()) {
442          return DOUBLE_REG;
443        } else {
444          throw new OptimizingCompilerException("getPhysicalRegisterType " + " unexpected " + r);
445        }
446      }
447    
448      /**
449       * Register names for each class. used in printing the IR
450       */
451      private static final String[] registerName = new String[getSize()];
452    
453      static {
454        String[] regName = registerName;
455        for (GPR r : GPR.values()) {
456          regName[r.ordinal() + FIRST_INT] = r.toString();
457        }
458        if (ArchConstants.SSE2_FULL) {
459          for (XMM r : XMM.values()) {
460            regName[r.ordinal() + FIRST_DOUBLE] = r.toString();
461          }
462        } else {
463          for (FPR r : FPR.values()) {
464            regName[r.ordinal() + FIRST_DOUBLE] = r.toString();
465          }
466        }
467        regName[THREAD_REGISTER.value()] = "TR";
468        regName[AF] = "AF";
469        regName[CF] = "CF";
470        regName[OF] = "OF";
471        regName[PF] = "PF";
472        regName[SF] = "SF";
473        regName[ZF] = "ZF";
474        regName[ST0] = "ST0";
475        regName[ST1] = "ST1";
476      }
477    
478      /**
479       * Get the register name for a register with a particular number in the
480       * pool
481       */
482      public static String getName(int number) {
483        return registerName[number];
484      }
485    
486      /**
487       * Get the spill size for a register with a particular type
488       * @param type one of INT_REG, DOUBLE_REG, SPECIAL_REG
489       */
490      public static int getSpillSize(int type) {
491        if (VM.VerifyAssertions) {
492          VM._assert((type == INT_REG) || (type == DOUBLE_REG) || (type == SPECIAL_REG));
493        }
494        if (type == DOUBLE_REG) {
495          return 8;
496        } else {
497          return 4;
498        }
499      }
500    
501      /**
502       * Get the required spill alignment for a register with a particular type
503       * @param type one of INT_REG, DOUBLE_REG,  SPECIAL_REG
504       */
505      public static int getSpillAlignment(int type) {
506        if (VM.VerifyAssertions) {
507          VM._assert((type == INT_REG) || (type == DOUBLE_REG) || (type == SPECIAL_REG));
508        }
509        if (type == DOUBLE_REG) {
510          return 8;
511        } else {
512          return 4;
513        }
514      }
515    
516      @Override
517      public Enumeration<Register> enumerateAll() {
518        return new RangeEnumeration(0, getSize() - 1);
519      }
520    
521      @Override
522      public Enumeration<Register> enumerateGPRs() {
523        return new RangeEnumeration(FIRST_INT, FIRST_DOUBLE - 1);
524      }
525    
526      /**
527       * Enumerate all the FPRs in this set.
528       */
529      public Enumeration<Register> enumerateFPRs() {
530        return new RangeEnumeration(FIRST_DOUBLE, FIRST_SPECIAL - 1);
531      }
532    
533      @Override
534      public PhysicalRegisterEnumeration enumerateVolatileGPRs() {
535        Register[] r = new Register[NUM_VOLATILE_GPRS];
536        for (int i = 0; i < NUM_VOLATILE_GPRS; i++) {
537          r[i] = getGPR(VOLATILE_GPRS[i]);
538        }
539        return new PhysicalRegisterEnumeration(r);
540      }
541    
542      @Override
543      public PhysicalRegisterEnumeration enumerateNonvolatileGPRs() {
544        Register[] r = new Register[NUM_NONVOLATILE_GPRS];
545        for (int i = 0; i < NUM_NONVOLATILE_GPRS; i++) {
546          r[i] = getGPR(NONVOLATILE_GPRS[i]);
547        }
548        return new PhysicalRegisterEnumeration(r);
549      }
550    
551      @Override
552      public Enumeration<Register> enumerateNonvolatileGPRsBackwards() {
553        return new ReverseEnumerator<Register>(enumerateNonvolatileGPRs());
554      }
555    
556      @Override
557      public PhysicalRegisterEnumeration enumerateVolatileFPRs() {
558        Register[] r = new Register[NUM_VOLATILE_FPRS];
559        for (int i = 0; i < NUM_VOLATILE_FPRS; i++) {
560          r[i] = getFPR(VOLATILE_FPRS[i]);
561        }
562        return new PhysicalRegisterEnumeration(r);
563      }
564    
565      @Override
566      public PhysicalRegisterEnumeration enumerateNonvolatileFPRs() {
567        Register[] r = new Register[NUM_NONVOLATILE_FPRS];
568        for (int i = 0; i < NUM_NONVOLATILE_FPRS; i++) {
569          r[i] = getFPR(NONVOLATILE_FPRS[i]);
570        }
571        return new PhysicalRegisterEnumeration(r);
572      }
573    
574      /**
575       * Enumerate the volatile physical registers of a given class.
576       * @param regClass one of INT_REG, DOUBLE_REG, SPECIAL_REG
577       */
578      public Enumeration<Register> enumerateVolatiles(int regClass) {
579        switch (regClass) {
580          case INT_REG:
581            return enumerateVolatileGPRs();
582          case DOUBLE_REG:
583            return enumerateVolatileFPRs();
584          case SPECIAL_REG:
585            return EmptyEnumeration.emptyEnumeration();
586          default:
587            throw new OptimizingCompilerException("Unsupported volatile type");
588        }
589      }
590    
591      @Override
592      public Enumeration<Register> enumerateVolatiles() {
593        Enumeration<Register> e1 = enumerateVolatileGPRs();
594        Enumeration<Register> e2 = enumerateVolatileFPRs();
595        return new CompoundEnumerator<Register>(e1, e2);
596      }
597    
598      /**
599       * @return the set of volatile physical registers
600       */
601      public BitSet getVolatiles() {
602        return volatileSet;
603      }
604    
605      /**
606       * @return the set of FPR physical registers
607       */
608      public BitSet getFPRs() {
609        return fpSet;
610      }
611    
612      /**
613       * Enumerate the nonvolatile physical registers of a given class.
614       * @param regClass one of INT_REG, DOUBLE_REG, SPECIAL_REG
615       */
616      public Enumeration<Register> enumerateNonvolatiles(int regClass) {
617        switch (regClass) {
618          case INT_REG:
619            return enumerateNonvolatileGPRs();
620          case DOUBLE_REG:
621            return enumerateNonvolatileFPRs();
622          case SPECIAL_REG:
623            return EmptyEnumeration.emptyEnumeration();
624          default:
625            throw new OptimizingCompilerException("Unsupported non-volatile type");
626        }
627      }
628    
629      /**
630       * Enumerate the nonvolatile physical registers of a given class,
631       * backwards
632       * @param regClass one of INT_REG, DOUBLE_REG, SPECIAL_REG
633       */
634      public Enumeration<Register> enumerateNonvolatilesBackwards(int regClass) {
635        return new ReverseEnumerator<Register>(enumerateNonvolatiles(regClass));
636      }
637    
638      /**
639       * An enumerator for use by the physical register utilities.
640       */
641      static final class PhysicalRegisterEnumeration implements Enumeration<Register> {
642        private int index;
643        private final Register[] r;
644    
645        PhysicalRegisterEnumeration(Register[] r) {
646          this.r = r;
647          this.index = 0;
648        }
649    
650        @Override
651        public Register nextElement() {
652          return r[index++];
653        }
654    
655        @Override
656        public boolean hasMoreElements() {
657          return (index < r.length);
658        }
659      }
660    
661      /**
662       * An enumerator for use by the physical register utilities.
663       */
664      final class RangeEnumeration implements Enumeration<Register> {
665        private final int end;
666        private int index;
667        private final int exclude; // an index in the register range to exclude
668    
669        RangeEnumeration(int start, int end) {
670          this.end = end;
671          this.exclude = -1;
672          this.index = start;
673        }
674    
675        RangeEnumeration(int start, int end, int exclude) {
676          this.end = end;
677          this.exclude = exclude;
678          this.index = start;
679        }
680    
681        @Override
682        public Register nextElement() {
683          if (index == exclude) index++;
684          return reg[index++];
685        }
686    
687        @Override
688        public boolean hasMoreElements() {
689          if (index == exclude) index++;
690          return (index <= end);
691        }
692      }
693    }