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