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}