1 pnkfelix 1.1.2.5  // Code.java, created Fri Jul 30 13:41:35 1999 by pnkfelix
  2 pnkfelix 1.1.2.5  // Copyright (C) 1999 Felix S. Klock II <pnkfelix@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.StrongARM;
  5 andyb    1.1.2.1  
  6 pnkfelix 1.1.2.5  import harpoon.IR.Tree.CanonicalTreeCode;
  7 pnkfelix 1.1.2.5  import harpoon.IR.Assem.Instr;
  8 pnkfelix 1.1.2.5  import harpoon.Analysis.Instr.TempInstrPair;
  9 pnkfelix 1.1.2.5  import harpoon.Backend.Generic.Frame;
 10 andyb    1.1.2.1  import harpoon.ClassFile.HCode;
 11 andyb    1.1.2.1  import harpoon.ClassFile.HCodeFactory;
 12 pnkfelix 1.1.2.5  import harpoon.ClassFile.HMethod;
 13 andyb    1.1.2.1  import harpoon.Temp.Temp;
 14 andyb    1.1.2.1  
 15 pnkfelix 1.1.2.5  import java.util.List;
 16 pnkfelix 1.1.2.5  import java.util.HashMap;
 17 pnkfelix 1.1.2.21 import java.util.Iterator;
 18 pnkfelix 1.1.2.5  import java.util.Map;
 19 pnkfelix 1.1.2.14 import java.util.Arrays;
 20 pnkfelix 1.1.2.14 import java.util.Collections;
 21 pnkfelix 1.1.2.14 import java.util.Collection;
 22 pnkfelix 1.1.2.14 import java.util.Set;
 23 pnkfelix 1.1.2.14 import java.util.HashSet;
 24 andyb    1.1.2.1  
 25 cananian 1.5      import net.cscott.jutil.Util;
 26 andyb    1.1.2.1  /**
 27 pnkfelix 1.1.2.5   * <code>Code</code> is a code-view for StrongARM assembly.
 28 pnkfelix 1.1.2.5   * 
 29 pnkfelix 1.1.2.5   * @author  Felix S. Klock II <pnkfelix@mit.edu>
 30 cananian 1.6       * @version $Id: Code.java,v 1.6 2004/02/08 03:21:04 cananian Exp $
 31 andyb    1.1.2.1   */
 32 cananian 1.1.2.23 class Code extends harpoon.Backend.Generic.Code {
 33 andyb    1.1.2.1      public static final String codename = "strongarm";
 34 andyb    1.1.2.1  
 35 pnkfelix 1.1.2.14     private static final boolean DEBUG = false;
 36 pnkfelix 1.1.2.14 
 37 pnkfelix 1.1.2.21     private Map tempInstrToRegisterMap;
 38 pnkfelix 1.1.2.21     private RegFileInfo regFileInfo;
 39 andyb    1.1.2.3  
 40 pnkfelix 1.1.2.5      /** Creates a <code>Code</code>. */
 41 pnkfelix 1.1.2.5      public Code(harpoon.IR.Tree.Code treeCode) {
 42 cananian 1.1.2.18         super(treeCode);
 43 pnkfelix 1.1.2.13 
 44 pnkfelix 1.1.2.13         // need to cast the return type to a StrongARM.RegFileInfo
 45 cananian 1.1.2.18         regFileInfo = (RegFileInfo) this.frame.getRegFileInfo();
 46 cananian 1.3.2.1          assert regFileInfo != null : "Need non-null regfileinfo";
 47 pnkfelix 1.1.2.13 
 48 pnkfelix 1.1.2.13         tempInstrToRegisterMap = new HashMap();
 49 pnkfelix 1.1.2.5      }
 50 andyb    1.1.2.1  
 51 andyb    1.1.2.1      public String getName() { return codename; }
 52 andyb    1.1.2.1  
 53 pnkfelix 1.1.2.5      /**
 54 pnkfelix 1.1.2.5       * Returns a code factory for <code>Code</code>, given a 
 55 pnkfelix 1.1.2.5       * code factory for <code>CanonicalTreeCode</code>.
 56 pnkfelix 1.1.2.5       * <BR> <B>effects:</B> if <code>hcf</code> is a code factory for
 57 pnkfelix 1.1.2.5       *      <code>CanonicalTreeCode</code>, then creates and returns a code
 58 pnkfelix 1.1.2.5       *      factory for <code>Code</code>.  Else passes
 59 pnkfelix 1.1.2.5       *      <code>hcf</code> to
 60 pnkfelix 1.1.2.5       *      <code>CanonicalTreeCode.codeFactory()</code>, and reattempts to
 61 pnkfelix 1.1.2.5       *      create a code factory for <code>Code</code> from the
 62 pnkfelix 1.1.2.5       *      code factory returned by <code>CanonicalTreeCode</code>.
 63 pnkfelix 1.1.2.5       * @see CanonicalTreeCode#codeFactory(HCodeFactory, Frame)
 64 pnkfelix 1.1.2.5       */
 65 pnkfelix 1.1.2.5      public static HCodeFactory codeFactory(final HCodeFactory hcf, 
 66 pnkfelix 1.1.2.5                                             final Frame frame) {
 67 pnkfelix 1.1.2.5          if(hcf.getCodeName().equals(CanonicalTreeCode.codename)){
 68 pnkfelix 1.1.2.5              return new HCodeFactory() {
 69 pnkfelix 1.1.2.5                  public HCode convert(HMethod m) {
 70 pnkfelix 1.1.2.5                      harpoon.IR.Tree.Code tc = 
 71 pnkfelix 1.1.2.5                          (harpoon.IR.Tree.Code) hcf.convert(m);
 72 pnkfelix 1.1.2.5                      return (tc == null) ? null : new Code(tc);
 73 pnkfelix 1.1.2.5                  }
 74 pnkfelix 1.1.2.5                  public void clear(HMethod m) { hcf.clear(m); }
 75 pnkfelix 1.1.2.5                  public String getCodeName() { return codename; }
 76 pnkfelix 1.1.2.5              };
 77 pnkfelix 1.1.2.5          } else {
 78 pnkfelix 1.1.2.5              // recursion can be ugly some times.
 79 pnkfelix 1.1.2.5              return codeFactory(CanonicalTreeCode.
 80 pnkfelix 1.1.2.5                                 codeFactory(hcf, frame), frame);
 81 pnkfelix 1.1.2.5          }
 82 pnkfelix 1.1.2.5      }
 83 pnkfelix 1.1.2.5      
 84 pnkfelix 1.1.2.27     public List getRegisters(Instr i, Temp val) {
 85 cananian 1.3.2.1          assert i != null : "Code.getRegisters(null, Temp) undefined";
 86 pnkfelix 1.1.2.14         if (val instanceof TwoWordTemp) {
 87 pnkfelix 1.1.2.14             TwoWordTemp t = (TwoWordTemp) val;
 88 pnkfelix 1.1.2.14             Temp low = get(i, t.getLow());
 89 pnkfelix 1.1.2.14             Temp high = get(i, t.getHigh());
 90 cananian 1.3.2.1              assert low != null : ((true)?"low reg is null"
 91 pnkfelix 1.1.2.24                         : "low register for "+val+" in "+i+ 
 92 pnkfelix 1.1.2.24                           " should not be null");
 93 cananian 1.3.2.1              assert high != null : ((true)?"high reg is null"
 94 pnkfelix 1.1.2.24                         : "high register for "+val+" in "+i+
 95 pnkfelix 1.1.2.24                           " should not be null");
 96 pnkfelix 1.1.2.14             return Arrays.asList(new Temp[]{ low, high });
 97 pnkfelix 1.1.2.14                                  
 98 pnkfelix 1.1.2.14         } else {
 99 pnkfelix 1.1.2.28             Temp t;
100 pnkfelix 1.1.2.28             if ( regFileInfo.isRegister(val) ) {
101 pnkfelix 1.1.2.28                 t = val;
102 pnkfelix 1.1.2.28             } else {
103 pnkfelix 1.1.2.28                 t = get(i, val);
104 cananian 1.3.2.1                  assert t != null : "register for "+val+" in "+i+
105 cananian 1.3.2.1                              " should not be null";
106 pnkfelix 1.1.2.28             }
107 pnkfelix 1.1.2.27             return Collections.nCopies(1, t);
108 pnkfelix 1.1.2.14         }
109 pnkfelix 1.1.2.14     }
110 pnkfelix 1.1.2.14 
111 pnkfelix 1.1.2.13     /** This returns null or a register temp. */
112 pnkfelix 1.1.2.5      private Temp get(Instr instr, Temp val) {
113 pnkfelix 1.1.2.13         Temp reg = 
114 pnkfelix 1.1.2.13             (Temp) tempInstrToRegisterMap.get
115 pnkfelix 1.1.2.13             (new TempInstrPair(instr, val)); 
116 pnkfelix 1.1.2.13         if(reg == null) return null;
117 cananian 1.3.2.1          assert regFileInfo.isRegister(reg) : ((true)?"should be a reg"
118 pnkfelix 1.1.2.24                      : "Temp: "+reg+" should be a reg in "+
119 pnkfelix 1.1.2.24                        "Instr: "+instr+", Val: "+val);
120 pnkfelix 1.1.2.13         return reg;
121 andyb    1.1.2.1      }
122 andyb    1.1.2.1  
123 pnkfelix 1.1.2.5      
124 pnkfelix 1.1.2.20     public String getRegisterName(final Instr instr,
125 pnkfelix 1.1.2.5                                       final Temp val, 
126 pnkfelix 1.1.2.5                                       final String suffix) {
127 pnkfelix 1.1.2.5          String s=null;
128 pnkfelix 1.1.2.5          if (val instanceof TwoWordTemp) {
129 pnkfelix 1.1.2.5              // parse suffix
130 pnkfelix 1.1.2.5              TwoWordTemp t = (TwoWordTemp) val;
131 pnkfelix 1.1.2.5              Temp reg = null;
132 pnkfelix 1.1.2.5              if (suffix.startsWith("l")) {
133 pnkfelix 1.1.2.5                  // low
134 pnkfelix 1.1.2.5                  reg = get(instr, t.getLow());
135 pnkfelix 1.1.2.5              } else if (suffix.startsWith("h")) {
136 pnkfelix 1.1.2.5                  // high
137 pnkfelix 1.1.2.5                  reg = get(instr, t.getHigh());
138 pnkfelix 1.1.2.7              } else if (suffix.trim().equals("")) {
139 pnkfelix 1.1.2.22                 if (true) return "TW"+val;
140 cananian 1.3.2.1                  assert false : ("BREAK!  empty suffix " +
141 pnkfelix 1.1.2.9                              "suffix: " + suffix + "\n" +
142 pnkfelix 1.1.2.9                              "instr: " + instr + "\n" + 
143 pnkfelix 1.1.2.14                             "instr str: " + instr.getAssem() + "\n"+
144 pnkfelix 1.1.2.9                              "temp: " + val);
145 pnkfelix 1.1.2.5              } else {
146 cananian 1.3.2.1                  assert false : "BREAK!  This parsing needs to be "+
147 cananian 1.1.2.6                              "fixed, strongarm has a lot more cases than this."+
148 pnkfelix 1.1.2.7                              "\n suffix: "+ suffix + "\n" +
149 cananian 1.1.2.6                              "Alternatively, the pattern could be trying to "+
150 cananian 1.1.2.6                              "use a TwoWordTemp without the appropriate "+
151 cananian 1.3.2.1                              "double word modifier (l, h) in " + instr;
152 pnkfelix 1.1.2.5              }
153 pnkfelix 1.1.2.5              if(reg != null) {
154 pnkfelix 1.1.2.5                  s = reg.name() + suffix.substring(1);
155 pnkfelix 1.1.2.5              } else {
156 pnkfelix 1.1.2.5                  s = val.name() + suffix;
157 pnkfelix 1.1.2.5              }
158 pnkfelix 1.1.2.5          } else { // single word; nothing special
159 pnkfelix 1.1.2.5              Temp reg = get(instr, val);
160 pnkfelix 1.1.2.5              
161 cananian 1.3.2.1              assert !suffix.startsWith("l") &&
162 cananian 1.3.2.1                          !suffix.startsWith("h") : (true) ? "suffix not allowed " 
163 pnkfelix 1.1.2.24                         : "Shouldn't " +
164 pnkfelix 1.1.2.24                           "have 'l' or 'h' suffix with Temp: " + 
165 pnkfelix 1.1.2.24                           val + " Instrs: " + 
166 pnkfelix 1.1.2.24                           instr.getPrev() + ", " + 
167 pnkfelix 1.1.2.24                           instr + ", " + 
168 cananian 1.3.2.1                            instr.getNext();
169 pnkfelix 1.1.2.5  
170 pnkfelix 1.1.2.5              if(reg != null) {
171 pnkfelix 1.1.2.5                  s = reg.name() + suffix;
172 pnkfelix 1.1.2.5              } else {
173 pnkfelix 1.1.2.5                  s = val.name() + suffix;
174 pnkfelix 1.1.2.5              }
175 pnkfelix 1.1.2.5          }
176 cananian 1.3.2.1          // assert s.indexOf("r0l") == -1 && s.indexOf("r0h") == -1 &&
177 cananian 1.3.2.1          // s.indexOf("r1l") == -1 && s.indexOf("r1h") == -1 : // "Improper parsing of " + suffix + " in " + instr + " " + val.getClass().getName();
178 pnkfelix 1.1.2.5  
179 pnkfelix 1.1.2.5          return s;
180 pnkfelix 1.1.2.5      }
181 pnkfelix 1.1.2.5  
182 pnkfelix 1.1.2.14 
183 pnkfelix 1.1.2.14     // overriding superclass implementation to add
184 pnkfelix 1.1.2.14     // architecture-dependant assertions (in an effort to fail-fast)
185 cananian 1.1.2.19     public String toAssem(Instr instr) {
186 pnkfelix 1.1.2.14         if (DEBUG) {
187 pnkfelix 1.1.2.14             // these constraint checks may be flawed; I'm getting
188 pnkfelix 1.1.2.14             // assertion failures on good code, i think...
189 pnkfelix 1.1.2.14 
190 pnkfelix 1.1.2.14             // check that constants are all contained in eight-bit chunks
191 pnkfelix 1.1.2.14             String assem = instr.getAssem();
192 pnkfelix 1.1.2.14             int begin = assem.lastIndexOf('#');
193 pnkfelix 1.1.2.14             
194 pnkfelix 1.1.2.14             
195 pnkfelix 1.1.2.14             if (begin != -1) {
196 pnkfelix 1.1.2.14                 int end = assem.length();
197 pnkfelix 1.1.2.14                 final char[] endChars = new char[]{ '\n', '@', ']', ' '};
198 pnkfelix 1.1.2.14                 for(int i=0; i<endChars.length; i++) {
199 pnkfelix 1.1.2.14                     int e = assem.lastIndexOf(endChars[i], end);
200 pnkfelix 1.1.2.14                     if (e > begin) end = e;
201 pnkfelix 1.1.2.14                     // System.out.println(assem.substring(begin+1, end));
202 pnkfelix 1.1.2.14                 }
203 pnkfelix 1.1.2.14                 
204 pnkfelix 1.1.2.14                 String constStr = assem.substring(begin+1, end);
205 pnkfelix 1.1.2.14                 int v = 0;
206 pnkfelix 1.1.2.14                 try { 
207 pnkfelix 1.1.2.14                     v = Integer.parseInt(constStr);
208 pnkfelix 1.1.2.14                 } catch (NumberFormatException e) {
209 pnkfelix 1.1.2.14                     System.out.println("bad const extraction");
210 pnkfelix 1.1.2.14                     System.out.println("\'"+constStr+"\'");
211 pnkfelix 1.1.2.14                     System.out.println(" from "+instr+"("+begin+","+end+")");
212 cananian 1.3.2.1                      assert false;
213 pnkfelix 1.1.2.14                 }
214 pnkfelix 1.1.2.14             
215 cananian 1.3.2.1                  assert isValidConst(v) || isValidConst(-v) : true?"const form err"
216 pnkfelix 1.1.2.24                             : "const form err of "+v+" in "+
217 cananian 1.3.2.1                                instr+"("+begin+","+end+")";
218 pnkfelix 1.1.2.14             }
219 pnkfelix 1.1.2.15         } // end if(DEBUG)
220 pnkfelix 1.1.2.15 
221 cananian 1.1.2.19         return super.toAssem(instr);
222 pnkfelix 1.1.2.14     }
223 pnkfelix 1.1.2.14 
224 pnkfelix 1.1.2.14     public static boolean isValidConst(final int val) {
225 pnkfelix 1.1.2.14         // FSK: stealing code from CSA again...
226 pnkfelix 1.1.2.14         int v;
227 pnkfelix 1.1.2.14         int r;
228 pnkfelix 1.1.2.14         
229 pnkfelix 1.1.2.14         v = val;
230 pnkfelix 1.1.2.14         r=0;
231 pnkfelix 1.1.2.14         for ( ; v!=0; r++) 
232 pnkfelix 1.1.2.14             v &= ~(0xFF << ((Util.ffs(v)-1) & ~1));
233 pnkfelix 1.1.2.14         return (r <= 1) ;
234 pnkfelix 1.1.2.14     }
235 pnkfelix 1.1.2.14 
236 pnkfelix 1.1.2.25     // runs once / ref / instr
237 pnkfelix 1.1.2.5      /** Assigns register(s) to the <code>Temp</code> pseudoReg. 
238 pnkfelix 1.1.2.5          <BR><B>requires:</B> <code>regs</code> is one of the
239 pnkfelix 1.1.2.5              <code>List</code>s returned by
240 pnkfelix 1.1.2.5              <code>SAFrame.suggestRegAssignment()</code> for
241 pnkfelix 1.1.2.5              <code>pseudoReg</code>.
242 pnkfelix 1.1.2.5          <BR><B>effects:</B> Associates the register <code>Temp</code>s
243 pnkfelix 1.1.2.5              in <code>regs</code> with (<code>instr</code> x
244 pnkfelix 1.1.2.5              <code>pseudoReg</code>) in such a manner that
245 pnkfelix 1.1.2.5              <code>getRegisterName(instr, psuedoReg, suffix)</code>
246 pnkfelix 1.1.2.5              will return the name associated with the appropriate
247 pnkfelix 1.1.2.5              register in <code>regs</code>.  
248 pnkfelix 1.1.2.5      */
249 pnkfelix 1.1.2.5      public void assignRegister(final Instr instr, 
250 pnkfelix 1.1.2.5                                 final Temp pseudoReg,
251 pnkfelix 1.1.2.5                                 final List regs) {
252 cananian 1.6              for (Object tO : regs) {
253 cananian 1.6                  Temp t = (Temp) tO;
254 cananian 1.3.2.2              assert regFileInfo.isRegister(t)
255 cananian 1.3.2.2                  : "every element of "+regs+" should be register, but "+t+
256 cananian 1.3.2.2                  "is not.";
257 pnkfelix 1.1.2.21         }
258 pnkfelix 1.1.2.21 
259 pnkfelix 1.1.2.5          if (pseudoReg instanceof TwoWordTemp) {
260 pnkfelix 1.1.2.5              TwoWordTemp t = (TwoWordTemp) pseudoReg;
261 cananian 1.3.2.1              assert regs.size() == 2 : "wrong reg assignment";
262 pnkfelix 1.1.2.13             tempInstrToRegisterMap.put
263 pnkfelix 1.1.2.5                  (new TempInstrPair(instr, t.getLow()), regs.get(0));
264 pnkfelix 1.1.2.13             tempInstrToRegisterMap.put
265 pnkfelix 1.1.2.5                  (new TempInstrPair(instr, t.getHigh()), regs.get(1));
266 pnkfelix 1.1.2.5          } else {
267 cananian 1.3.2.1              assert regs.size() == 1 : "wrong reg assignment";
268 pnkfelix 1.1.2.13             tempInstrToRegisterMap.put
269 pnkfelix 1.1.2.5                  (new TempInstrPair(instr, pseudoReg), regs.get(0));
270 pnkfelix 1.1.2.10         }
271 pnkfelix 1.1.2.11  
272 pnkfelix 1.1.2.11         // Register Constraint check
273 pnkfelix 1.1.2.25         if (DEBUG && 
274 pnkfelix 1.1.2.25             ((instr.getAssem().indexOf("mul ") != -1) ||
275 pnkfelix 1.1.2.25              (instr.getAssem().indexOf("mla ") != -1))) {
276 pnkfelix 1.1.2.12             Object rm = get(instr, instr.use()[0]);
277 pnkfelix 1.1.2.12             Object rd = get(instr, instr.def()[0]);
278 cananian 1.3.2.1              assert rm == null || !rm.equals(rd) : ("rd:"+rd+" and rm:"+rm+" must be different in mul");
279 pnkfelix 1.1.2.11         }                       
280 pnkfelix 1.1.2.10     }
281 pnkfelix 1.1.2.12 
282 pnkfelix 1.1.2.12     public void removeAssignment(Instr instr, Temp preg) {
283 pnkfelix 1.1.2.12         if (preg instanceof TwoWordTemp) {
284 pnkfelix 1.1.2.12             TwoWordTemp t = (TwoWordTemp) preg;
285 pnkfelix 1.1.2.13             tempInstrToRegisterMap.remove
286 pnkfelix 1.1.2.12                 (new TempInstrPair(instr, t.getLow()));
287 pnkfelix 1.1.2.13             tempInstrToRegisterMap.remove
288 pnkfelix 1.1.2.12                 (new TempInstrPair(instr, t.getHigh()));
289 pnkfelix 1.1.2.12         } else {
290 pnkfelix 1.1.2.13             tempInstrToRegisterMap.remove
291 pnkfelix 1.1.2.12                 (new TempInstrPair(instr, preg));
292 pnkfelix 1.1.2.12         }
293 pnkfelix 1.1.2.12     }
294 pnkfelix 1.1.2.12 
295 pnkfelix 1.1.2.10 
296 pnkfelix 1.1.2.10     public boolean registerAssigned(Instr instr, Temp pr) {
297 pnkfelix 1.1.2.10         if (pr instanceof TwoWordTemp) {
298 pnkfelix 1.1.2.10             TwoWordTemp t = (TwoWordTemp) pr;
299 pnkfelix 1.1.2.10             return 
300 pnkfelix 1.1.2.13                 (tempInstrToRegisterMap.
301 pnkfelix 1.1.2.10                  keySet().contains
302 pnkfelix 1.1.2.10                  (new TempInstrPair(instr, t.getLow()))
303 pnkfelix 1.1.2.10                  &&
304 pnkfelix 1.1.2.13                  tempInstrToRegisterMap.
305 pnkfelix 1.1.2.10                  keySet().contains
306 pnkfelix 1.1.2.10                  (new TempInstrPair(instr, t.getHigh())));
307 pnkfelix 1.1.2.10         } else {
308 pnkfelix 1.1.2.10             return 
309 pnkfelix 1.1.2.13                 (tempInstrToRegisterMap.
310 pnkfelix 1.1.2.10                  keySet().contains
311 pnkfelix 1.1.2.10                  (new TempInstrPair(instr, pr)));
312 pnkfelix 1.1.2.5          }
313 andyb    1.1.2.1      }
314 cananian 1.2      }