1 cananian 1.1.2.7  // RegFileInfo.java, created Tue Nov  2  2:07:04 1999 by andyb
  2 andyb    1.1.2.1  // Copyright (C) 1999 Andrew Berkheimer <andyb@mit.edu>
  3 andyb    1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 andyb    1.1.2.1  package harpoon.Backend.Sparc;
  5 andyb    1.1.2.1  
  6 andyb    1.1.2.1  import harpoon.Backend.Generic.Frame;
  7 andyb    1.1.2.1  import harpoon.Backend.Generic.LocationFactory.Location;
  8 andyb    1.1.2.8  import harpoon.Backend.Generic.RegFileInfo.SpillException;
  9 cananian 1.1.2.13 import harpoon.ClassFile.HCode.PrintCallback;
 10 andyb    1.1.2.3  import harpoon.ClassFile.HCodeElement;
 11 andyb    1.1.2.3  import harpoon.ClassFile.HClass;
 12 andyb    1.1.2.1  import harpoon.ClassFile.HData;
 13 andyb    1.1.2.3  import harpoon.ClassFile.HDataElement;
 14 andyb    1.1.2.3  import harpoon.IR.Tree.Type;
 15 andyb    1.1.2.3  import harpoon.IR.Tree.TreeFactory;
 16 andyb    1.1.2.3  import harpoon.IR.Tree.TEMP;
 17 andyb    1.1.2.3  import harpoon.IR.Tree.Data;
 18 andyb    1.1.2.3  import harpoon.IR.Tree.Exp;
 19 andyb    1.1.2.1  import harpoon.Temp.Temp;
 20 andyb    1.1.2.1  import harpoon.Temp.TempFactory;
 21 cananian 1.5      import net.cscott.jutil.LinearSet;
 22 cananian 1.5      import net.cscott.jutil.ListFactory;
 23 andyb    1.1.2.1  import harpoon.Util.Util;
 24 andyb    1.1.2.1  
 25 andyb    1.1.2.3  import java.util.ArrayList;
 26 andyb    1.1.2.3  import java.util.Arrays;
 27 andyb    1.1.2.1  import java.util.Collections;
 28 andyb    1.1.2.1  import java.util.Iterator;
 29 andyb    1.1.2.1  import java.util.Map;
 30 andyb    1.1.2.1  import java.util.Set;
 31 andyb    1.1.2.1  
 32 andyb    1.1.2.1  /**
 33 andyb    1.1.2.2   * <code>RegFileInfo</code> contains architecture specific information
 34 andyb    1.1.2.2   * about the registers for the Sparc architecture.  It also implements
 35 andyb    1.1.2.2   * the LocationFactory interface for allocating and tracking registers
 36 andyb    1.1.2.2   * which are used for tracking global data.
 37 andyb    1.1.2.1   *
 38 andyb    1.1.2.1   * @author  Andrew Berkheimer <andyb@mit.edu>
 39 cananian 1.5       * @version $Id: RegFileInfo.java,v 1.5 2004/02/08 01:57:50 cananian Exp $
 40 andyb    1.1.2.1   */
 41 andyb    1.1.2.1  public class RegFileInfo 
 42 andyb    1.1.2.1    extends harpoon.Backend.Generic.RegFileInfo 
 43 andyb    1.1.2.1    implements harpoon.Backend.Generic.LocationFactory
 44 andyb    1.1.2.1  {
 45 andyb    1.1.2.2      private final TempFactory regtf;
 46 andyb    1.1.2.6      private final Temp[] integerRegs;
 47 andyb    1.1.2.2      private final Temp[] generalRegs;
 48 andyb    1.1.2.6      private final Temp[] floatingRegs;
 49 andyb    1.1.2.6      private final Temp[] generalIntRegs;
 50 andyb    1.1.2.6      private final Temp[] allRegs;
 51 andyb    1.1.2.2      private final Set callerSaveRegs;
 52 andyb    1.1.2.2      private final Set calleeSaveRegs;
 53 andyb    1.1.2.2      private final Set liveOnExitRegs;
 54 andyb    1.1.2.3      private final Temp SP, FP;
 55 andyb    1.1.2.3      private final TempBuilder tb;
 56 andyb    1.1.2.1  
 57 andyb    1.1.2.3      public RegFileInfo(TempBuilder tb) {
 58 andyb    1.1.2.3          this.tb = tb;
 59 andyb    1.1.2.2  
 60 andyb    1.1.2.3          /* Sparc registers:
 61 andyb    1.1.2.3           *   %g0 - %g7: global, general registers. %g0 is zero register.
 62 andyb    1.1.2.3           *   %o0 - %o7: registers for local data and arguments to called
 63 andyb    1.1.2.3           *              subroutines. %o6 is stack pointer, %o7 is called
 64 andyb    1.1.2.3           *              subroutine return address.
 65 andyb    1.1.2.3           *   %l0 - %l7: local variables
 66 andyb    1.1.2.3           *   %i0 - %i7: registers for incoming subroutine arguments.
 67 andyb    1.1.2.3           *              %i6 is frame pointer and %i7 is subroutine return
 68 andyb    1.1.2.3           *              address.
 69 andyb    1.1.2.6           *   %f0 - %f31: floating point registewrs.
 70 andyb    1.1.2.3           */
 71 andyb    1.1.2.3          regtf = new TempFactory() {
 72 andyb    1.1.2.3              private int i = 0;
 73 andyb    1.1.2.3              private final String scope = "sparc-registers";
 74 andyb    1.1.2.3              private final String[] names = {"%g0", "%g1", "%g2", "%g3",
 75 andyb    1.1.2.3                  "%g4", "%g5", "%g6", "%g7", "%o0", "%o1", "%o2", "%o3",
 76 andyb    1.1.2.3                  "%o4", "%o5", "%sp", "%o7", "%l0", "%l1", "%l2", "%l3",
 77 andyb    1.1.2.3                  "%l4", "%l5", "%l6", "%l7", "%i0", "%i1", "%i2", "%i3",
 78 andyb    1.1.2.6                  "%i4", "%i5", "%fp", "%i7", "%f0", "%f1", "%f2", "%f3",
 79 andyb    1.1.2.6                  "%f4", "%f5", "%f6", "%f7", "%f8", "%f9", "%f10", "%f11",
 80 andyb    1.1.2.6                  "%f12", "%f13", "%f14", "%f15", "%f16", "%f17", "%f18", "%f19",
 81 andyb    1.1.2.6                  "%f20", "%f21", "%f22", "%f23", "%f24", "%f25", "%f26", "%f27",
 82 andyb    1.1.2.6                  "%f28", "%f29", "%f30", "%f31"};
 83 andyb    1.1.2.3  
 84 andyb    1.1.2.3              public String getScope() { return scope; }
 85 andyb    1.1.2.3              public synchronized String getUniqueID(String suggestion) {
 86 cananian 1.3.2.1                  assert i < names.length : "Already created all of "+
 87 cananian 1.3.2.1                              "the Register bound Temps!!!";
 88 andyb    1.1.2.3                  i++;
 89 andyb    1.1.2.3                  return names[i-1];
 90 andyb    1.1.2.3              }
 91 andyb    1.1.2.3          };
 92 andyb    1.1.2.3  
 93 andyb    1.1.2.6          integerRegs = new Temp[32]; 
 94 andyb    1.1.2.6          generalIntRegs = new Temp[27];
 95 andyb    1.1.2.6          floatingRegs = new Temp[32];
 96 andyb    1.1.2.6          generalRegs = new Temp[59];
 97 andyb    1.1.2.6          allRegs = new Temp[64];
 98 andyb    1.1.2.3  
 99 andyb    1.1.2.3          int j = 0;
100 andyb    1.1.2.3          for (int i = 0; i < 32; i++) {
101 andyb    1.1.2.6              integerRegs[i] = new Temp(regtf);
102 andyb    1.1.2.9              allRegs[i] = integerRegs[i];
103 andyb    1.1.2.3              if ((i != 0) && (i != 14) && (i != 15) && (i != 30) && (i != 31)) {
104 andyb    1.1.2.6                  generalIntRegs[j] = integerRegs[i];
105 andyb    1.1.2.6                  generalRegs[j] = integerRegs[i];
106 andyb    1.1.2.3                  j++;
107 andyb    1.1.2.3              }
108 andyb    1.1.2.3          }
109 andyb    1.1.2.6          for (int i = 0; i < 32; i++) {
110 andyb    1.1.2.6              floatingRegs[i] = new Temp(regtf);
111 andyb    1.1.2.6              generalRegs[i+27] = floatingRegs[i];
112 andyb    1.1.2.6              allRegs[i+32] = floatingRegs[i];
113 andyb    1.1.2.6          }
114 andyb    1.1.2.3  
115 andyb    1.1.2.6          SP = allRegs[14];
116 andyb    1.1.2.6          FP = allRegs[30];
117 andyb    1.1.2.2   
118 andyb    1.1.2.10         // live on exit: %fp, %sp, %o0: return value, %o7: return address
119 andyb    1.1.2.4          //               %g0: zero, always live
120 andyb    1.1.2.4          liveOnExitRegs = new LinearSet(5);  
121 andyb    1.1.2.4          liveOnExitRegs.add(FP);
122 andyb    1.1.2.4          liveOnExitRegs.add(SP);
123 andyb    1.1.2.6          liveOnExitRegs.add(allRegs[0]);
124 andyb    1.1.2.10         liveOnExitRegs.add(allRegs[8]);
125 andyb    1.1.2.10         liveOnExitRegs.add(allRegs[15]);
126 andyb    1.1.2.4   
127 andyb    1.1.2.4          // caller saved: clobbered by callee
128 andyb    1.1.2.4          // %g0-%g7, %o0-%o5, %o7 
129 andyb    1.1.2.4          callerSaveRegs = new LinearSet(15);
130 andyb    1.1.2.4          for (int i = 0; i < 16; i++)
131 andyb    1.1.2.6              if (i != 14)  /* i = 14 -> allRegs[14] -> %sp */
132 andyb    1.1.2.6                  callerSaveRegs.add(allRegs[i]);
133 andyb    1.1.2.4  
134 andyb    1.1.2.4          // callee needs to save these itself
135 andyb    1.1.2.4          // none - all callee saving is done by the magic save
136 andyb    1.1.2.4          // instruction, go sparc go woohoo
137 andyb    1.1.2.4          calleeSaveRegs = new LinearSet(0);
138 andyb    1.1.2.1      }
139 andyb    1.1.2.3  
140 andyb    1.1.2.3      // Sparc backend specific helpers...
141 andyb    1.1.2.3  
142 andyb    1.1.2.3      final Temp SP() { return SP; }
143 andyb    1.1.2.3      final Temp FP() { return FP; }
144 andyb    1.1.2.3  
145 andyb    1.1.2.3      // And now for the implementation of Generic.RegFileInfo
146 andyb    1.1.2.3                 
147 andyb    1.1.2.1      public Set liveOnExit() { 
148 andyb    1.1.2.1          return Collections.unmodifiableSet(liveOnExitRegs); 
149 andyb    1.1.2.1      }
150 andyb    1.1.2.1   
151 andyb    1.1.2.1      public Set callerSave() { 
152 andyb    1.1.2.3          return Collections.unmodifiableSet(callerSaveRegs); 
153 andyb    1.1.2.1      }
154 andyb    1.1.2.1  
155 andyb    1.1.2.1      public Set calleeSave() { 
156 andyb    1.1.2.3          return Collections.unmodifiableSet(calleeSaveRegs); 
157 andyb    1.1.2.1      }
158 andyb    1.1.2.1  
159 andyb    1.1.2.1      public TempFactory regTempFactory() { return regtf; }
160 pnkfelix 1.1.2.12 
161 pnkfelix 1.1.2.12     public boolean isRegister(Temp t) {
162 pnkfelix 1.1.2.12         return t.tempFactory() == regTempFactory();
163 pnkfelix 1.1.2.12     }
164 andyb    1.1.2.1  
165 andyb    1.1.2.1      public Iterator suggestRegAssignment(Temp t, final Map regFile)
166 andyb    1.1.2.8          throws SpillException {
167 andyb    1.1.2.1  
168 andyb    1.1.2.3          final ArrayList suggests = new ArrayList();
169 andyb    1.1.2.3          final ArrayList spills = new ArrayList();
170 andyb    1.1.2.6          Temp[] possibleRegs;        
171 andyb    1.1.2.6  
172 andyb    1.1.2.6          if (tb.isFloatingPoint(t)) {
173 andyb    1.1.2.6              possibleRegs = floatingRegs;
174 andyb    1.1.2.6          } else {
175 andyb    1.1.2.6              possibleRegs = generalIntRegs;
176 andyb    1.1.2.6          }
177 andyb    1.1.2.1  
178 andyb    1.1.2.3          if (tb.isTwoWord(t)) {
179 andyb    1.1.2.6              /* sparc32 doubles must be aligned on adjacent registers,
180 andyb    1.1.2.6                 either 0/1, 2/3, 4/5, etc... */
181 andyb    1.1.2.6              for (int i = 0; i < possibleRegs.length - 1; i+=2) {
182 andyb    1.1.2.6                  Temp[] assign = new Temp[] { possibleRegs[i],
183 andyb    1.1.2.6                                               possibleRegs[i+1] };
184 andyb    1.1.2.3                  if ((regFile.get(assign[0]) == null) &&
185 andyb    1.1.2.3                      (regFile.get(assign[1]) == null)) {
186 andyb    1.1.2.3                      suggests.add(Arrays.asList(assign));
187 andyb    1.1.2.3                  } else {
188 andyb    1.1.2.3                      Set s = new LinearSet(2);
189 andyb    1.1.2.3                      s.add(assign[0]);
190 andyb    1.1.2.3                      s.add(assign[1]);
191 andyb    1.1.2.3                      spills.add(s);
192 andyb    1.1.2.3                  }
193 andyb    1.1.2.3              }
194 andyb    1.1.2.3          } else {
195 andyb    1.1.2.6              for (int i = 0; i < possibleRegs.length; i++) {
196 andyb    1.1.2.6                  if ((regFile.get(possibleRegs[i]) == null)) {
197 andyb    1.1.2.6                      suggests.add(ListFactory.singleton(possibleRegs[i]));
198 andyb    1.1.2.3                  } else {
199 andyb    1.1.2.3                      Set s = new LinearSet(1);
200 andyb    1.1.2.6                      s.add(possibleRegs[i]);
201 andyb    1.1.2.3                      spills.add(s);
202 andyb    1.1.2.3                  }
203 andyb    1.1.2.3              }
204 andyb    1.1.2.3          }
205 andyb    1.1.2.3          if (suggests.isEmpty()) {
206 andyb    1.1.2.8              throw new SpillException() {
207 andyb    1.1.2.3                  public Iterator getPotentialSpills() {
208 andyb    1.1.2.3                      return spills.iterator();
209 andyb    1.1.2.3                  }
210 andyb    1.1.2.3              };
211 andyb    1.1.2.3          }
212 andyb    1.1.2.3          return suggests.iterator();
213 andyb    1.1.2.3      }
214 andyb    1.1.2.1  
215 andyb    1.1.2.1      public Temp[] getAllRegisters() {
216 andyb    1.1.2.6          return (Temp[]) Util.safeCopy(Temp.arrayFactory, allRegs);
217 andyb    1.1.2.1      }
218 andyb    1.1.2.1  
219 andyb    1.1.2.6      public Temp getRegister(int index) { return allRegs[index]; }
220 andyb    1.1.2.1  
221 andyb    1.1.2.1      public Temp[] getGeneralRegisters() {
222 andyb    1.1.2.3          return (Temp[]) Util.safeCopy(Temp.arrayFactory, generalRegs);
223 andyb    1.1.2.1      }
224 andyb    1.1.2.1  
225 andyb    1.1.2.1      // implementing LocationFactory
226 andyb    1.1.2.1  
227 andyb    1.1.2.3      // start allocating registers from %g7 down to %g1
228 andyb    1.1.2.3      private int regtop = 7;
229 andyb    1.1.2.3      private boolean makeLocationDataCalled = false;
230 andyb    1.1.2.3  
231 andyb    1.1.2.1      public Location allocateLocation(final int type) {
232 cananian 1.3.2.1          assert Type.isValid(type) : "Invalid type";
233 cananian 1.3.2.1          assert type != Type.LONG && type != Type.DOUBLE : "Doubleword global locations not implemented";
234 cananian 1.3.2.1          assert !makeLocationDataCalled : "Cannot allocate location - already ran makeLocationData";
235 andyb    1.1.2.3  
236 andyb    1.1.2.3          // Currently just uses the %g registers - nothing fancy yet.
237 cananian 1.3.2.1          assert regtop > 0 : "Sorry, can't do any more global locations";
238 andyb    1.1.2.3      
239 andyb    1.1.2.6          final Temp allocreg = allRegs[regtop--];
240 andyb    1.1.2.3  
241 andyb    1.1.2.3          calleeSaveRegs.remove(allocreg);
242 andyb    1.1.2.3          callerSaveRegs.remove(allocreg);
243 andyb    1.1.2.3          liveOnExitRegs.remove(allocreg);
244 andyb    1.1.2.3  
245 andyb    1.1.2.3          return new Location() {
246 andyb    1.1.2.3              public Exp makeAccessor(TreeFactory tf, HCodeElement source) {
247 andyb    1.1.2.3                  return new TEMP(tf, source, type, allocreg);
248 andyb    1.1.2.3              }
249 andyb    1.1.2.3          };
250 andyb    1.1.2.1      }
251 andyb    1.1.2.1  
252 andyb    1.1.2.3      // not allocating memory for these yet, so just return an empty 
253 andyb    1.1.2.3      // HData for now
254 andyb    1.1.2.1      public HData makeLocationData(final Frame f) {
255 andyb    1.1.2.3          makeLocationDataCalled = true;
256 andyb    1.1.2.3          return new Data("location-data", f) {
257 andyb    1.1.2.3              public HClass getHClass() { return null; }
258 andyb    1.1.2.3              public HDataElement getRootElement() { return null; }
259 cananian 1.1.2.13             public void print(java.io.PrintWriter pw, PrintCallback cb) {
260 andyb    1.1.2.3                  pw.println("--- no data ---");
261 andyb    1.1.2.3              }
262 andyb    1.1.2.3          };
263 andyb    1.1.2.1      }
264 cananian 1.2      }