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 }