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