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.compilers.opt.ir.ppc;
014
015import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.CONDITION_REG;
016import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.CR;
017import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.CTR;
018import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.DOUBLE_REG;
019import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.FIRST_CONDITION;
020import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.FIRST_DOUBLE;
021import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.FIRST_DOUBLE_PARAM;
022import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.FIRST_INT;
023import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.FIRST_INT_PARAM;
024import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.FIRST_INT_RETURN;
025import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.FIRST_SPECIAL;
026import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.INT_REG;
027import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.LR;
028import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.NUMBER_DOUBLE_PARAM;
029import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.NUMBER_INT_PARAM;
030import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.SPECIAL_REG;
031import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.TL;
032import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.TU;
033import static org.jikesrvm.compilers.opt.regalloc.ppc.PhysicalRegisterConstants.XER;
034import static org.jikesrvm.ppc.RegisterConstants.FIRST_NONVOLATILE_FPR;
035import static org.jikesrvm.ppc.RegisterConstants.FIRST_NONVOLATILE_GPR;
036import static org.jikesrvm.ppc.RegisterConstants.FIRST_SCRATCH_FPR;
037import static org.jikesrvm.ppc.RegisterConstants.FIRST_SCRATCH_GPR;
038import static org.jikesrvm.ppc.RegisterConstants.FIRST_VOLATILE_FPR;
039import static org.jikesrvm.ppc.RegisterConstants.FIRST_VOLATILE_GPR;
040import static org.jikesrvm.ppc.RegisterConstants.FRAME_POINTER;
041import static org.jikesrvm.ppc.RegisterConstants.JTOC_POINTER;
042import static org.jikesrvm.ppc.RegisterConstants.LAST_NONVOLATILE_FPR;
043import static org.jikesrvm.ppc.RegisterConstants.LAST_NONVOLATILE_GPR;
044import static org.jikesrvm.ppc.RegisterConstants.LAST_SCRATCH_FPR;
045import static org.jikesrvm.ppc.RegisterConstants.LAST_SCRATCH_GPR;
046import static org.jikesrvm.ppc.RegisterConstants.LAST_VOLATILE_FPR;
047import static org.jikesrvm.ppc.RegisterConstants.LAST_VOLATILE_GPR;
048import static org.jikesrvm.ppc.RegisterConstants.NUM_CRS;
049import static org.jikesrvm.ppc.RegisterConstants.NUM_FPRS;
050import static org.jikesrvm.ppc.RegisterConstants.NUM_GPRS;
051import static org.jikesrvm.ppc.RegisterConstants.NUM_NONVOLATILE_FPRS;
052import static org.jikesrvm.ppc.RegisterConstants.NUM_NONVOLATILE_GPRS;
053import static org.jikesrvm.ppc.RegisterConstants.NUM_SPECIALS;
054import static org.jikesrvm.ppc.RegisterConstants.THREAD_REGISTER;
055import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_DOUBLE;
056import static org.jikesrvm.runtime.UnboxedSizeConstants.BYTES_IN_ADDRESS;
057
058import java.util.Enumeration;
059
060import org.jikesrvm.VM;
061import org.jikesrvm.architecture.MachineRegister;
062import org.jikesrvm.compilers.opt.OptimizingCompilerException;
063import org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet;
064import org.jikesrvm.compilers.opt.ir.Register;
065import org.jikesrvm.compilers.opt.util.BitSet;
066import org.jikesrvm.compilers.opt.util.CompoundEnumerator;
067import org.jikesrvm.compilers.opt.util.ReverseEnumerator;
068import org.jikesrvm.util.EmptyEnumeration;
069
070/**
071 * This class represents a set of Registers corresponding to the
072 * PowerPC register set.
073 *
074 * <P> Implementation Notes:
075 * <P> Due to some historical ugliness not yet cleaned up, the register
076 * allocator depend on properties cached in the
077 * <code>next</code> field of Register.  The constructor sets the
078 * following properties:
079 * <ul>
080 * <li> The volatile GPRs form a linked list, starting with
081 * FIRST_VOLATILE_GPR and ending with LAST_SCRATCH_GPR
082 * <li> The volatile FPRs form a linked list, starting with
083 * FIRST_VOLATILE_FPR and ending with LAST_SCRATCH_FPR
084 * <li> The non-volatile GPRs form a linked list, starting with
085 * FIRST_NONVOLATILE_GPR and ending with LAST_NONVOLATILE_GPR
086 * <li> The non-volatile FPRs form a linked list, starting with
087 * FIRST_NONVOLATILE_FPR and ending with LAST_NONVOLATILE_FPR
088 * <li> The condition registers from a linked list, starting with
089 * FIRST_CONDITION and ending with LAST_CONDITION-1, which opt reserves for yieldpoints.
090 * </ul>
091 * <P> The register allocator allocates registers according to the order
092 * in these lists.  For volatile registers, it traverses the lists in
093 * order, starting with getFirstVolatile() and traversing with getNext().
094 * For non-volatiles, it traverses the lists
095 * <STRONG> Backwards </STRONG>, starting with getLastNonvolatile() and
096 * using getPrev().
097 * <P> TODO; clean up all this and provide appropriate enumerators
098 */
099public final class PhysicalRegisterSet extends GenericPhysicalRegisterSet {
100
101  /**
102   * This array holds a pool of objects representing physical registers
103   */
104  private final Register[] reg = new Register[getSize()];
105
106  /**
107   * The set of volatile registers; cached for efficiency
108   */
109  private final BitSet volatileSet;
110
111  /**
112   * The condition registers that we allocate
113   * To avoid expensive save/restores when
114   * making a JNI transition Jikes RVM only uses the
115   * CR that the 64 bit PowerPC ELF ABI defines to be volatile.
116   *
117   * We reserve one of the volatiles, CR7 for use only in yieldpoints.
118   * This ensures that a yieldpoint won't bash an allocated CR.
119   */
120  private static final int[] CR_NUMS = new int[]{0, 1, 5, 6};
121  private static final int TSR_REG = 7;
122
123  /**
124   * @return the total number of physical registers.
125   */
126  public static int getSize() {
127    return NUM_GPRS + NUM_FPRS + NUM_CRS + NUM_SPECIALS;
128  }
129
130  @Override
131  public int getNumberOfPhysicalRegisters() {
132    return getSize();
133  }
134
135  /**
136   * @return the total number of nonvolatile GPRs.
137   */
138  public static int getNumberOfNonvolatileGPRs() {
139    return NUM_NONVOLATILE_GPRS;
140  }
141
142  /**
143   * @return the total number of nonvolatile FPRs.
144   */
145  public static int getNumberOfNonvolatileFPRs() {
146    return NUM_NONVOLATILE_FPRS;
147  }
148
149  /**
150   * Constructor: set up a pool of physical registers.
151   */
152  public PhysicalRegisterSet() {
153
154    // 1. Create all the physical registers in the pool.
155    for (int i = 0; i < reg.length; i++) {
156      Register r = new Register(i);
157      r.setPhysical();
158      reg[i] = r;
159    }
160
161    // 2. Set the 'integer' attribute on each GPR
162    for (int i = FIRST_INT; i < FIRST_DOUBLE; i++) {
163      if (VM.BuildFor32Addr) {
164        reg[i].setInteger();
165      } else {
166        reg[i].setLong();
167      }
168    }
169
170    // 3. Set the 'double' attribute on each FPR
171    for (int i = FIRST_DOUBLE; i < FIRST_CONDITION; i++) {
172      reg[i].setDouble();
173    }
174
175    // 4. Set the 'condition' attribute on each CR
176    for (int i = FIRST_CONDITION; i < FIRST_SPECIAL; i++) {
177      reg[i].setCondition();
178    }
179
180    // 5. set up the volatile GPRs
181    for (int i = FIRST_VOLATILE_GPR.value(); i < LAST_VOLATILE_GPR.value(); i++) {
182      Register r = reg[i];
183      r.setVolatile();
184      r.linkWithNext(reg[i + 1]);
185    }
186    reg[LAST_VOLATILE_GPR.value()].setVolatile();
187    reg[LAST_VOLATILE_GPR.value()].linkWithNext(reg[FIRST_SCRATCH_GPR.value()]);
188    for (int i = FIRST_SCRATCH_GPR.value(); i < LAST_SCRATCH_GPR.value(); i++) {
189      Register r = reg[i];
190      r.setVolatile();
191      r.linkWithNext(reg[i + 1]);
192    }
193    reg[LAST_SCRATCH_GPR.value()].setVolatile();
194
195    // 6. set up the non-volatile GPRs
196    for (int i = FIRST_NONVOLATILE_GPR.value(); i < LAST_NONVOLATILE_GPR.value(); i++) {
197      Register r = reg[i];
198      r.setNonVolatile();
199      r.linkWithNext(reg[i + 1]);
200    }
201
202    // 7. set properties on some special registers
203    reg[THREAD_REGISTER.value()].setSpansBasicBlock();
204    reg[FRAME_POINTER.value()].setSpansBasicBlock();
205    reg[JTOC_POINTER.value()].setSpansBasicBlock();
206
207    // 8. set up the volatile FPRs
208    for (int i = FIRST_DOUBLE + FIRST_VOLATILE_FPR.value();
209         i < FIRST_DOUBLE + LAST_VOLATILE_FPR.value(); i++) {
210      Register r = reg[i];
211      r.setVolatile();
212      r.linkWithNext(reg[i + 1]);
213    }
214    reg[FIRST_DOUBLE + LAST_VOLATILE_FPR.value()].linkWithNext(reg[FIRST_DOUBLE + FIRST_SCRATCH_FPR.value()]);
215    reg[FIRST_DOUBLE + LAST_VOLATILE_FPR.value()].setVolatile();
216    if (FIRST_SCRATCH_FPR != LAST_SCRATCH_FPR) {
217      for (int i = FIRST_DOUBLE + FIRST_SCRATCH_FPR.value();
218           i < FIRST_DOUBLE + LAST_SCRATCH_FPR.value(); i++) {
219        Register r = reg[i];
220        r.setVolatile();
221        r.linkWithNext(reg[i + 1]);
222      }
223    }
224    reg[FIRST_DOUBLE + LAST_SCRATCH_FPR.value()].setVolatile();
225
226    // 9. set up the non-volatile FPRs
227    for (int i = FIRST_DOUBLE + FIRST_NONVOLATILE_FPR.value();
228         i < FIRST_DOUBLE + LAST_NONVOLATILE_FPR.value(); i++) {
229      Register r = reg[i];
230      r.setNonVolatile();
231      r.linkWithNext(reg[i + 1]);
232    }
233
234    // 10. set up the condition registers
235    int firstCR = -1;
236    int prevCR = -1;
237    for (int i : CR_NUMS) {
238      reg[FIRST_CONDITION + i].setVolatile();
239      if (prevCR != -1) {
240        reg[FIRST_CONDITION + prevCR].linkWithNext(reg[FIRST_CONDITION + i]);
241      }
242      prevCR = i;
243      if (firstCR == -1) {
244        firstCR = i;
245      }
246    }
247
248    // 11. cache the volatiles for efficiency
249    volatileSet = new BitSet(this);
250    for (Enumeration<Register> e = enumerateVolatiles(); e.hasMoreElements();) {
251      Register r = e.nextElement();
252      volatileSet.add(r);
253    }
254
255    // 12. Show which registers should be excluded from live analysis
256    reg[CTR].setExcludedLiveA();
257    reg[CR].setExcludedLiveA();
258    reg[TU].setExcludedLiveA();
259    reg[TL].setExcludedLiveA();
260    reg[XER].setExcludedLiveA();
261    reg[FRAME_POINTER.value()].setExcludedLiveA();
262    reg[JTOC_POINTER.value()].setExcludedLiveA();
263    reg[LR].setExcludedLiveA();
264  }
265
266  /**
267   * Is a certain physical register allocatable?
268   */
269  @Override
270  public boolean isAllocatable(Register r) {
271    if (r.number == THREAD_REGISTER.value() ||
272        r.number == FRAME_POINTER.value() ||
273        r.number == JTOC_POINTER.value()) {
274      return false;
275    } else {
276      return (r.number < FIRST_SPECIAL);
277    }
278  }
279
280  /**
281   * @return the XER register.
282   */
283  public Register getXER() {
284    return reg[XER];
285  }
286
287  /**
288   * @return the LR register;.
289   */
290  public Register getLR() {
291    return reg[LR];
292  }
293
294  /**
295   * @return the CTR register
296   */
297  public Register getCTR() {
298    return reg[CTR];
299  }
300
301  /**
302   * @return the TU register
303   */
304  public Register getTU() {
305    return reg[TU];
306  }
307
308  /**
309   * @return the TL register
310   */
311  public Register getTL() {
312    return reg[TL];
313  }
314
315  /**
316   * @return the CR register
317   */
318  public Register getCR() {
319    return reg[CR];
320  }
321
322  /**
323   * @return the JTOC register
324   */
325  public Register getJTOC() {
326    return reg[JTOC_POINTER.value()];
327  }
328
329  @Override
330  public Register getFP() {
331    return reg[FRAME_POINTER.value()];
332  }
333
334  @Override
335  public Register getTR() {
336    return reg[THREAD_REGISTER.value()];
337  }
338
339  /**
340   * @return the thread-switch register
341   */
342  public Register getTSR() {
343    return reg[FIRST_CONDITION + TSR_REG];
344  }
345
346  @Override
347  public Register getGPR(int n) {
348    return reg[FIRST_INT + n];
349  }
350
351  /**
352   * @return the nth physical GPR
353   */
354  @Override
355  public Register getGPR(MachineRegister n) {
356    return reg[FIRST_INT + n.value()];
357  }
358
359  /**
360   * @return the first scratch GPR
361   */
362  public Register getFirstScratchGPR() {
363    return reg[FIRST_SCRATCH_GPR.value()];
364  }
365
366  /**
367   * @return the last scratch GPR
368   */
369  public Register getLastScratchGPR() {
370    return reg[LAST_SCRATCH_GPR.value()];
371  }
372
373  /**
374   * @return the first volatile GPR
375   */
376  public Register getFirstVolatileGPR() {
377    return reg[FIRST_INT + FIRST_VOLATILE_GPR.value()];
378  }
379
380  /**
381   * @return the first nonvolatile GPR
382   */
383  public Register getFirstNonvolatileGPR() {
384    return reg[FIRST_INT + FIRST_NONVOLATILE_GPR.value()];
385  }
386
387  /**
388   * @return the last nonvolatile GPR
389   */
390  public Register getLastNonvolatileGPR() {
391    return reg[FIRST_INT + LAST_NONVOLATILE_GPR.value()];
392  }
393
394  @Override
395  public Register getFirstReturnGPR() {
396    return reg[FIRST_INT_RETURN];
397  }
398
399  @Override
400  public Register getFPR(int n) {
401    return reg[FIRST_DOUBLE + n];
402  }
403
404  /**
405   * @return the first scratch FPR
406   */
407  public Register getFirstScratchFPR() {
408    return reg[FIRST_DOUBLE + FIRST_SCRATCH_FPR.value()];
409  }
410
411  /**
412   * @return the first volatile FPR
413   */
414  public Register getFirstVolatileFPR() {
415    return reg[FIRST_DOUBLE + FIRST_VOLATILE_FPR.value()];
416  }
417
418  /**
419   * @return the last scratch FPR
420   */
421  public Register getLastScratchFPR() {
422    return reg[FIRST_DOUBLE + LAST_SCRATCH_FPR.value()];
423  }
424
425  /**
426   * @return the first nonvolatile FPR
427   */
428  public Register getFirstNonvolatileFPR() {
429    return reg[FIRST_DOUBLE + FIRST_NONVOLATILE_FPR.value()];
430  }
431
432  /**
433   * @return the last nonvolatile FPR
434   */
435  public Register getLastNonvolatileFPR() {
436    return reg[FIRST_DOUBLE + LAST_NONVOLATILE_FPR.value()];
437  }
438
439  /**
440   * @param n number of the condition register
441   * @return the nth physical condition register
442   */
443  public Register getConditionRegister(int n) {
444    return reg[FIRST_CONDITION + n];
445  }
446
447  /**
448   * @return the first condition
449   */
450  public Register getFirstConditionRegister() {
451    return reg[FIRST_CONDITION];
452  }
453
454  /**
455   * @return the first volatile CR
456   */
457  public Register getFirstVolatileConditionRegister() {
458    if (VM.VerifyAssertions) {
459      VM._assert(getFirstConditionRegister() != getTSR());
460    }
461    return getFirstConditionRegister();
462  }
463
464  @Override
465  public Register get(int n) {
466    return reg[n];
467  }
468
469  /**
470   * @return the first volatile physical register of a given class
471   * @param regClass one of INT_REG, DOUBLE_REG, CONDITION_REG, or
472   * SPECIAL_REG
473   */
474  public Register getFirstVolatile(int regClass) {
475    switch (regClass) {
476      case INT_REG:
477        return getFirstVolatileGPR();
478      case DOUBLE_REG:
479        return getFirstVolatileFPR();
480      case CONDITION_REG:
481        return getFirstVolatileConditionRegister();
482      case SPECIAL_REG:
483        return null;
484      default:
485        throw new OptimizingCompilerException("Unknown register class");
486    }
487  }
488
489  /**
490   * @return the first nonvolatile physical register of a given class
491   * @param regClass one of INT_REG, DOUBLE_REG, CONDITION_REG, or
492   * SPECIAL_REG
493   */
494  public Register getLastNonvolatile(int regClass) {
495    switch (regClass) {
496      case INT_REG:
497        return getLastNonvolatileGPR();
498      case DOUBLE_REG:
499        return getLastNonvolatileFPR();
500      case CONDITION_REG:
501        return null;
502      case SPECIAL_REG:
503        return null;
504      default:
505        throw new OptimizingCompilerException("Unknown register class");
506    }
507  }
508
509  /**
510   * Given a symbolic register, return a cdoe that gives the physical
511   * register type to hold the value of the symbolic register.
512   * @param r a symbolic register
513   * @return one of INT_REG, DOUBLE_REG, or CONDITION_REG
514   */
515  public static int getPhysicalRegisterType(Register r) {
516    if (r.isInteger() || r.isLong() || r.isAddress()) {
517      return INT_REG;
518    } else if (r.isFloatingPoint()) {
519      return DOUBLE_REG;
520    } else if (r.isCondition()) {
521      return CONDITION_REG;
522    } else {
523      throw new OptimizingCompilerException("getPhysicalRegisterType " + " unexpected " + r);
524    }
525  }
526
527  /**
528   * Given a physical register (XER, LR, or CTR), return the integer that
529   * denotes the PowerPC Special Purpose Register (SPR) in the PPC
530   * instruction set.  See p.129 of PPC ISA book
531   *
532   * @param r a physical register (XER, LR or CTR)
533   * @return the integer that denotes the PowerPC Special Purpose Register (SPR)
534   *  in the PPC  instruction set.
535   */
536  public byte getSPR(Register r) {
537    if (VM.VerifyAssertions) {
538      VM._assert((r == getXER()) || (r == getLR()) || (r == getCTR()));
539    }
540    if (r == getXER()) {
541      return 1;
542    } else if (r == getLR()) {
543      return 8;
544    } else if (r == getCTR()) {
545      return 9;
546    } else {
547      throw new OptimizingCompilerException("Invalid SPR");
548    }
549  }
550
551  /**
552   * register names for each class. used in printing the IR
553   * The indices for "FP" and "JTOC" should always match the
554   * final static values of int FP and int JTOC defined below.
555   */
556  private static final String[] registerName = new String[getSize()];
557
558  static {
559    String[] regName = registerName;
560    for (int i = 0; i < NUM_GPRS; i++) {
561      regName[i + FIRST_INT] = "R" + i;
562    }
563    for (int i = 0; i < NUM_FPRS; i++) {
564      regName[i + FIRST_DOUBLE] = "F" + i;
565    }
566    for (int i = 0; i < NUM_CRS; i++) {
567      regName[i + FIRST_CONDITION] = "C" + i;
568    }
569    regName[JTOC_POINTER.value()] = "JTOC";
570    regName[FRAME_POINTER.value()] = "FP";
571    regName[THREAD_REGISTER.value()] = "TR";
572    regName[XER] = "XER";
573    regName[LR] = "LR";
574    regName[CTR] = "CTR";
575    regName[TU] = "TU";
576    regName[TL] = "TL";
577    regName[CR] = "CR";
578  }
579
580  static final int TEMP = FIRST_INT;   // temporary register (currently r0)
581
582  /**
583   * @return R0, a temporary register
584   */
585  public Register getTemp() {
586    return reg[TEMP];
587  }
588
589  /**
590   * @param number a register number
591   * @return the register name for a register with a particular number in the
592   * pool
593   */
594  public static String getName(int number) {
595    return registerName[number];
596  }
597
598  /**
599   * Gets the spill size for a register with a particular type
600   * @param type one of INT_REG, DOUBLE_REG, CONDITION_REG, SPECIAL_REG
601   * @return the spill size in bytes
602   */
603  public static int getSpillSize(int type) {
604    if (VM.VerifyAssertions) {
605      VM._assert((type == INT_REG) || (type == DOUBLE_REG) || (type == CONDITION_REG) || (type == SPECIAL_REG));
606    }
607    if (type == DOUBLE_REG) {
608      return BYTES_IN_DOUBLE;
609    } else {
610      return BYTES_IN_ADDRESS;
611    }
612  }
613
614  /**
615   * Gets the required spill alignment for a register with a particular type
616   * @param type one of INT_REG, DOUBLE_REG, CONDITION_REG, SPECIAL_REG
617   * @return the alignment in bytes
618   */
619  public static int getSpillAlignment(int type) {
620    if (VM.VerifyAssertions) {
621      VM._assert((type == INT_REG) || (type == DOUBLE_REG) || (type == CONDITION_REG) || (type == SPECIAL_REG));
622    }
623    if (type == DOUBLE_REG) {
624      return BYTES_IN_DOUBLE;
625    } else {
626      return BYTES_IN_ADDRESS;
627    }
628  }
629
630  @Override
631  public Enumeration<Register> enumerateAll() {
632    return new PhysicalRegisterEnumeration(0, getSize() - 1);
633  }
634
635  @Override
636  public Enumeration<Register> enumerateGPRs() {
637    return new PhysicalRegisterEnumeration(FIRST_INT, FIRST_DOUBLE - 1);
638  }
639
640  @Override
641  public Enumeration<Register> enumerateVolatileGPRs() {
642    return new PhysicalRegisterEnumeration(FIRST_INT + FIRST_VOLATILE_GPR.value(), FIRST_INT + LAST_SCRATCH_GPR.value());
643  }
644
645  static {
646    // enumerateVolatileGPRs relies on volatiles & scratches being
647    // contiguous; so let's make sure that is the case!
648    if (VM.VerifyAssertions) {
649      VM._assert(LAST_VOLATILE_GPR.value() + 1 == FIRST_SCRATCH_GPR.value());
650    }
651  }
652
653  /**
654   * Enumerate the first n GPR parameters.
655   * @param n count of GPR parameters to enumerate
656   * @return enumeration of the first n GPR parameters
657   */
658  public Enumeration<Register> enumerateGPRParameters(int n) {
659    if (VM.VerifyAssertions) {
660      VM._assert(n <= NUMBER_INT_PARAM);
661    }
662    return new PhysicalRegisterEnumeration(FIRST_INT_PARAM, FIRST_INT_PARAM + n - 1);
663  }
664
665  @Override
666  public Enumeration<Register> enumerateNonvolatileGPRs() {
667    return new PhysicalRegisterEnumeration(FIRST_INT + FIRST_NONVOLATILE_GPR.value(), FIRST_INT + LAST_NONVOLATILE_GPR.value());
668  }
669
670  @Override
671  public Enumeration<Register> enumerateNonvolatileGPRsBackwards() {
672    return new ReverseEnumerator<Register>(enumerateNonvolatileGPRs());
673  }
674
675  /**
676   * Enumerates all the volatile FPRs in this set.
677   * NOTE: This assumes the scratch FPRs are numbered immediately
678   * <em> before</em> the volatile FPRs.
679   * @return an enumeration containing all volatile FPRs in this set
680   */
681  @Override
682  public Enumeration<Register> enumerateVolatileFPRs() {
683    return new PhysicalRegisterEnumeration(FIRST_DOUBLE + FIRST_SCRATCH_FPR.value(), FIRST_DOUBLE + LAST_VOLATILE_FPR.value());
684  }
685
686  /**
687   * Enumerates the first n FPR parameters.
688   * @param n count of FPR parameters
689   * @return an enumeration containing the firs n FPRs
690   */
691  public Enumeration<Register> enumerateFPRParameters(int n) {
692    if (VM.VerifyAssertions) {
693      VM._assert(n <= NUMBER_DOUBLE_PARAM);
694    }
695    return new PhysicalRegisterEnumeration(FIRST_DOUBLE_PARAM, FIRST_DOUBLE_PARAM + n - 1);
696  }
697
698  @Override
699  public Enumeration<Register> enumerateNonvolatileFPRs() {
700    return new PhysicalRegisterEnumeration(FIRST_DOUBLE + FIRST_NONVOLATILE_FPR.value(), FIRST_DOUBLE + LAST_NONVOLATILE_FPR.value());
701  }
702
703  /**
704   * Enumerates the volatile physical condition registers.
705   * Note that the TSR is non-volatile.
706   * @return an enumeration of the volatile condition registers
707   */
708  public Enumeration<Register> enumerateVolatileConditionRegisters() {
709    return new Enumeration<Register>() {
710      private int idx = 0;
711
712      @Override
713      public Register nextElement() {
714        return reg[FIRST_CONDITION + CR_NUMS[idx++]];
715      }
716
717      @Override
718      public boolean hasMoreElements() {
719        return idx < CR_NUMS.length;
720      }
721    };
722  }
723
724  /**
725   * Enumerates the non-volatile physical condition registers.
726   * Note that only the TSR is non-volatile.
727   *
728   * @return an enumeration containing only TSR
729   */
730  public Enumeration<Register> enumerateNonvolatileConditionRegisters() {
731    return new PhysicalRegisterEnumeration(0, -1);
732  }
733
734  /**
735   * Enumerate the volatile physical registers of a given class.
736   * @param regClass one of INT_REG, DOUBLE_REG, CONDITION_REG
737   * @return enumeration containing the physical registers of the
738   *  desired class
739   */
740  @Override
741  public Enumeration<Register> enumerateVolatiles(int regClass) {
742    switch (regClass) {
743      case INT_REG:
744        return enumerateVolatileGPRs();
745      case DOUBLE_REG:
746        return enumerateVolatileFPRs();
747      case CONDITION_REG:
748        return enumerateVolatileConditionRegisters();
749      case SPECIAL_REG:
750        return EmptyEnumeration.emptyEnumeration();
751      default:
752        throw new OptimizingCompilerException("Unsupported volatile type");
753    }
754  }
755
756  @Override
757  public Enumeration<Register> enumerateVolatiles() {
758    Enumeration<Register> e1 = enumerateVolatileGPRs();
759    Enumeration<Register> e2 = enumerateVolatileFPRs();
760    Enumeration<Register> e3 = enumerateVolatileConditionRegisters();
761    return new CompoundEnumerator<Register>(e1, new CompoundEnumerator<Register>(e2, e3));
762  }
763
764  /**
765   * @return a set of all the volatile registers.
766   */
767  public BitSet getVolatiles() {
768    return volatileSet;
769  }
770
771  /**
772   * Enumerate the nonvolatile physical registers of a given class.
773   * @param regClass one of INT_REG, DOUBLE_REG, CONDITION_REG
774   * @return the non-volatile physical registers of the given class
775   */
776  public Enumeration<Register> enumerateNonvolatiles(int regClass) {
777    switch (regClass) {
778      case INT_REG:
779        return enumerateNonvolatileGPRs();
780      case DOUBLE_REG:
781        return enumerateNonvolatileFPRs();
782      case CONDITION_REG:
783        return enumerateNonvolatileConditionRegisters();
784      case SPECIAL_REG:
785        return EmptyEnumeration.emptyEnumeration();
786      default:
787        throw new OptimizingCompilerException("Unsupported non-volatile type");
788    }
789  }
790
791  @Override
792  public Enumeration<Register> enumerateNonvolatilesBackwards(int regClass) {
793    return new ReverseEnumerator<Register>(enumerateNonvolatiles(regClass));
794  }
795
796  /**
797   * @param r a physical register
798   * @return If the passed in physical register r is used as a GPR parameter register,
799   * return the index into the GPR parameters for r.  Otherwise, return -1;
800   */
801  public int getGPRParamIndex(Register r) {
802    if ((r.number < FIRST_INT_PARAM) || (r.number > LAST_VOLATILE_GPR.value())) {
803      return -1;
804    } else {
805      return r.number - FIRST_INT_PARAM;
806    }
807  }
808
809  /**
810   * @param r a physical register
811   * @return If the passed in physical register r is used as an FPR parameter register,
812   * return the index into the FPR parameters for r.  Otherwise, return -1;
813   */
814  public int getFPRParamIndex(Register r) {
815    if ((r.number < FIRST_DOUBLE_PARAM) || (r.number > LAST_VOLATILE_FPR.value())) {
816      return -1;
817    } else {
818      return r.number - FIRST_DOUBLE_PARAM;
819    }
820  }
821
822  /**
823   * @param r a register
824   * @return If r is used as the first half of a (long) register pair, return
825   * the second half of the pair.
826   */
827  public Register getSecondHalf(Register r) {
828    int n = r.number;
829    return get(n + 1);
830  }
831
832  /**
833   * An enumerator for use by the physical register utilities.
834   */
835  final class PhysicalRegisterEnumeration implements Enumeration<Register> {
836    private final int end;
837    private int index;
838
839    PhysicalRegisterEnumeration(int start, int end) {
840      this.end = end;
841      this.index = start;
842    }
843
844    @Override
845    public Register nextElement() {
846      return reg[index++];
847    }
848
849    @Override
850    public boolean hasMoreElements() {
851      return (index <= end);
852    }
853  }
854}