1 pnkfelix 1.1.2.1  // InstrBuilder.java, created Fri Sep 10 23:37:52 1999 by pnkfelix
  2 pnkfelix 1.1.2.1  // Copyright (C) 1999 Felix S. Klock II <pnkfelix@mit.edu>
  3 pnkfelix 1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 pnkfelix 1.1.2.1  package harpoon.Backend.StrongARM;
  5 pnkfelix 1.1.2.1  
  6 pnkfelix 1.1.2.1  import harpoon.IR.Assem.Instr;
  7 pnkfelix 1.1.2.1  import harpoon.IR.Assem.InstrMEM;
  8 pnkfelix 1.1.2.1  import harpoon.IR.Assem.InstrLABEL;
  9 pnkfelix 1.1.2.1  import harpoon.Temp.Temp;
 10 pnkfelix 1.1.2.1  import harpoon.Temp.Label;
 11 pnkfelix 1.1.2.1  
 12 pnkfelix 1.1.2.1  import java.util.List;
 13 pnkfelix 1.1.2.2  import java.util.Iterator;
 14 pnkfelix 1.1.2.1  import java.util.Arrays;
 15 pnkfelix 1.1.2.1  
 16 cananian 1.5      import net.cscott.jutil.Util;
 17 pnkfelix 1.1.2.1  /** <code>StrongARM.InstrBuilder</code> is an <code>Generic.InstrBuilder</code> for the
 18 pnkfelix 1.1.2.1      StrongARM architecture.
 19 pnkfelix 1.1.2.1  
 20 pnkfelix 1.1.2.1      @author  Felix S. Klock II <pnkfelix@mit.edu>
 21 cananian 1.5          @version $Id: InstrBuilder.java,v 1.5 2004/02/08 01:57:59 cananian Exp $
 22 pnkfelix 1.1.2.1   */
 23 pnkfelix 1.1.2.1  public class InstrBuilder extends harpoon.Backend.Generic.InstrBuilder {
 24 pnkfelix 1.1.2.2  
 25 pnkfelix 1.1.2.12     // making offset limit a bit smaller than 1023 to allow for
 26 pnkfelix 1.1.2.12     // .fpoffset margin
 27 pnkfelix 1.1.2.12     private static final int OFFSET_LIMIT = 1000;
 28 pnkfelix 1.1.2.2  
 29 pnkfelix 1.1.2.1      RegFileInfo rfInfo;
 30 pnkfelix 1.1.2.1  
 31 pnkfelix 1.1.2.1      /* helper macro. */
 32 pnkfelix 1.1.2.10     private final Temp FP() { 
 33 pnkfelix 1.1.2.10         return rfInfo.FP;
 34 pnkfelix 1.1.2.1      }
 35 pnkfelix 1.1.2.1      
 36 pnkfelix 1.1.2.1      InstrBuilder(RegFileInfo rfInfo) {
 37 pnkfelix 1.1.2.1          super();
 38 pnkfelix 1.1.2.1          this.rfInfo = rfInfo;
 39 pnkfelix 1.1.2.1      }
 40 pnkfelix 1.1.2.1  
 41 pnkfelix 1.1.2.1      // TODO: override makeStore/Load(List, int, Instr) to take
 42 pnkfelix 1.1.2.1      // advantage of StrongARM's multi-register memory operations.   
 43 pnkfelix 1.1.2.1  
 44 pnkfelix 1.1.2.2      public int getSize(Temp t) {
 45 pnkfelix 1.1.2.2          if (t instanceof TwoWordTemp) {
 46 pnkfelix 1.1.2.2              return 2; 
 47 pnkfelix 1.1.2.2          } else {
 48 pnkfelix 1.1.2.2              return 1;
 49 pnkfelix 1.1.2.2          }
 50 pnkfelix 1.1.2.2      }
 51 pnkfelix 1.1.2.2  
 52 pnkfelix 1.1.2.2      // note to self; add code to generate multi-instruction code for
 53 pnkfelix 1.1.2.2      // loading Temps that cross the OFFSET_LIMIT; instead of using a
 54 pnkfelix 1.1.2.10     // Constant Offset, just manually increment and decrement FP (for
 55 pnkfelix 1.1.2.2      // Loads, can actually increment the target-register so that 
 56 pnkfelix 1.1.2.2  
 57 pnkfelix 1.1.2.1      public List makeLoad(Temp r, int offset, Instr template) {
 58 cananian 1.3.2.1          // assert offset < OFFSET_LIMIT : //           "offset " + offset + " is too large";
 59 pnkfelix 1.1.2.2  
 60 pnkfelix 1.1.2.2          if (offset < OFFSET_LIMIT) { // common case
 61 pnkfelix 1.1.2.3              String[] strs = getLdrAssemStrs(r, offset);
 62 cananian 1.3.2.1              assert strs.length == 1 ||
 63 cananian 1.3.2.1                          strs.length == 2;
 64 pnkfelix 1.1.2.2  
 65 pnkfelix 1.1.2.2              if (strs.length == 2) {
 66 pnkfelix 1.1.2.2                  InstrMEM load1 = 
 67 pnkfelix 1.1.2.2                      new InstrMEM(template.getFactory(), template,
 68 pnkfelix 1.1.2.2                                   strs[0],
 69 pnkfelix 1.1.2.2                                   new Temp[]{ r },
 70 pnkfelix 1.1.2.10                                  new Temp[]{ FP()  });
 71 pnkfelix 1.1.2.2                  InstrMEM load2 = 
 72 pnkfelix 1.1.2.2                      new InstrMEM(template.getFactory(), template,
 73 pnkfelix 1.1.2.2                                   strs[1],
 74 pnkfelix 1.1.2.2                                   new Temp[]{ r },
 75 pnkfelix 1.1.2.10                                  new Temp[]{ FP()  });
 76 pnkfelix 1.1.2.2                  load2.layout(load1, null);
 77 pnkfelix 1.1.2.2                  return Arrays.asList(new InstrMEM[] { load1, load2 });
 78 pnkfelix 1.1.2.2              } else {
 79 pnkfelix 1.1.2.2                  InstrMEM load = 
 80 pnkfelix 1.1.2.2                      new InstrMEM(template.getFactory(), template,
 81 pnkfelix 1.1.2.2                                   strs[0],
 82 pnkfelix 1.1.2.2                                   new Temp[]{ r },
 83 pnkfelix 1.1.2.10                                  new Temp[]{ FP()  });
 84 pnkfelix 1.1.2.2                  return Arrays.asList(new InstrMEM[] { load });
 85 pnkfelix 1.1.2.2              }
 86 pnkfelix 1.1.2.2          } else {
 87 pnkfelix 1.1.2.3              // System.out.println("Offset exceeded!");
 88 pnkfelix 1.1.2.3  
 89 pnkfelix 1.1.2.10             // need to wrap load with instructions to shift FP down
 90 pnkfelix 1.1.2.2              // and up again, and need to make it *ONE* Instr so that
 91 pnkfelix 1.1.2.2              // they do not get seperated.  Also, note that this is
 92 pnkfelix 1.1.2.2              // safe since StrongARM does not seem to have normal
 93 pnkfelix 1.1.2.2              // interrupts 
 94 pnkfelix 1.1.2.2  
 95 pnkfelix 1.1.2.7              int newOffset = offset;
 96 pnkfelix 1.1.2.7              while (newOffset >= OFFSET_LIMIT) {
 97 pnkfelix 1.1.2.7                  newOffset -= OFFSET_LIMIT;
 98 pnkfelix 1.1.2.7              }
 99 pnkfelix 1.1.2.3              String assem = 
100 pnkfelix 1.1.2.8                  getWrappedAssem(getLdrAssemStrs(r, newOffset), 
101 pnkfelix 1.1.2.8                                  offset, "`s0"); 
102 pnkfelix 1.1.2.3  
103 pnkfelix 1.1.2.2              return Arrays.asList
104 pnkfelix 1.1.2.2                  (new InstrMEM[] 
105 pnkfelix 1.1.2.2                   { new InstrMEM(template.getFactory(), template,
106 pnkfelix 1.1.2.2                                  assem, 
107 pnkfelix 1.1.2.2                                  new Temp[]{ r }, 
108 pnkfelix 1.1.2.10                                 new Temp[]{ FP() }) });
109 pnkfelix 1.1.2.2          }
110 pnkfelix 1.1.2.2      }
111 pnkfelix 1.1.2.2  
112 pnkfelix 1.1.2.3      private String[] getLdrAssemStrs(Temp r, int offset) {
113 pnkfelix 1.1.2.3          if (r instanceof TwoWordTemp) {
114 pnkfelix 1.1.2.3              return new String[] {
115 pnkfelix 1.1.2.10                 "ldr `d0l, [`s0, #.fpoffset-" +(4*offset) + "] " ,
116 pnkfelix 1.1.2.11                     "ldr `d0h, [`s0, #.fpoffset-" +(4*(offset+1)) + "] @ restore2" };
117 pnkfelix 1.1.2.3          } else {
118 pnkfelix 1.1.2.10             return new String[] { "ldr `d0, [`s0, #.fpoffset-" 
119 pnkfelix 1.1.2.11                                       +(4*offset) + "] @ restore" };
120 pnkfelix 1.1.2.3          }
121 pnkfelix 1.1.2.3      }
122 pnkfelix 1.1.2.3  
123 pnkfelix 1.1.2.3      private String[] getStrAssemStrs(Temp r, int offset) {
124 pnkfelix 1.1.2.3          if (r instanceof TwoWordTemp) {
125 pnkfelix 1.1.2.3              return new String[] {
126 pnkfelix 1.1.2.10                 "str `s0l, [`s1, #.fpoffset-" +(4*offset) + "] " ,
127 pnkfelix 1.1.2.11                     "str `s0h, [`s1, #.fpoffset-" +(4*(offset+1)) + "] @ spill2" };
128 pnkfelix 1.1.2.3          } else {
129 pnkfelix 1.1.2.10             return new String[] { "str `s0, [`s1, #.fpoffset-" 
130 pnkfelix 1.1.2.10                                       +(4*offset) + "] @ spill" };
131 pnkfelix 1.1.2.3          }
132 pnkfelix 1.1.2.3      }
133 pnkfelix 1.1.2.3  
134 pnkfelix 1.1.2.1      public List makeStore(Temp r, int offset, Instr template) {
135 cananian 1.3.2.1          // assert offset < OFFSET_LIMIT : //             "offset " + offset + " is too large";
136 pnkfelix 1.1.2.3  
137 pnkfelix 1.1.2.3          if (offset < OFFSET_LIMIT) { // common case
138 cananian 1.3.2.1              // assert harpoon.Backend.StrongARM.
139 cananian 1.3.2.1              //             Code.isValidConst( 4*offset ) : //              "invalid offset: "+(4*offset);
140 pnkfelix 1.1.2.3              String[] strs = getStrAssemStrs(r, offset);
141 cananian 1.3.2.1              assert strs.length == 1 || 
142 cananian 1.3.2.1                          strs.length == 2;
143 pnkfelix 1.1.2.3              
144 pnkfelix 1.1.2.3              if (strs.length == 2) {
145 pnkfelix 1.1.2.6                  System.out.println("In makeStore, twoWord case");
146 pnkfelix 1.1.2.6  
147 pnkfelix 1.1.2.3                  InstrMEM store1 = 
148 pnkfelix 1.1.2.3                      new InstrMEM(template.getFactory(), template,
149 pnkfelix 1.1.2.3                                   strs[0],
150 pnkfelix 1.1.2.3                                   new Temp[]{ },
151 pnkfelix 1.1.2.10                                  new Temp[]{ r , FP() });
152 pnkfelix 1.1.2.3                  InstrMEM store2 = 
153 pnkfelix 1.1.2.3                      new InstrMEM(template.getFactory(), template,
154 pnkfelix 1.1.2.3                                   strs[1],
155 pnkfelix 1.1.2.3                                   new Temp[]{ },
156 pnkfelix 1.1.2.10                                  new Temp[]{ r , FP() });
157 pnkfelix 1.1.2.3                  store2.layout(store1, null);
158 cananian 1.3.2.1                  assert store1.getNext() == store2 : "store1.next == store2";
159 cananian 1.3.2.1                  assert store2.getPrev() == store1 : "store2.prev == store1";
160 pnkfelix 1.1.2.3                  return Arrays.asList(new InstrMEM[]{ store1, store2 });
161 pnkfelix 1.1.2.3              } else {
162 pnkfelix 1.1.2.6  
163 pnkfelix 1.1.2.3                  InstrMEM store = 
164 pnkfelix 1.1.2.3                      new InstrMEM(template.getFactory(), template,
165 pnkfelix 1.1.2.3                                   strs[0],
166 pnkfelix 1.1.2.3                                   new Temp[]{ },
167 pnkfelix 1.1.2.10                                  new Temp[]{ r , FP() });
168 pnkfelix 1.1.2.3                  return Arrays.asList(new InstrMEM[] { store });
169 pnkfelix 1.1.2.3              }
170 pnkfelix 1.1.2.3          } else {
171 pnkfelix 1.1.2.10             // need to wrap store with instructions to shift FP down
172 pnkfelix 1.1.2.3              // and up again, and need to make it *ONE* Instr
173 pnkfelix 1.1.2.3              
174 pnkfelix 1.1.2.7              int newOffset = offset;
175 pnkfelix 1.1.2.7              while (newOffset >= OFFSET_LIMIT) {
176 pnkfelix 1.1.2.7                  newOffset -= OFFSET_LIMIT;
177 pnkfelix 1.1.2.7              }
178 pnkfelix 1.1.2.3              String assem = 
179 pnkfelix 1.1.2.8                  getWrappedAssem(getStrAssemStrs(r, newOffset), 
180 pnkfelix 1.1.2.8                                  offset, "`s1");
181 pnkfelix 1.1.2.3  
182 pnkfelix 1.1.2.3              return Arrays.asList
183 pnkfelix 1.1.2.3                  (new InstrMEM[]
184 pnkfelix 1.1.2.3                   { new InstrMEM(template.getFactory(), template,
185 pnkfelix 1.1.2.3                                  assem,
186 pnkfelix 1.1.2.3                                  new Temp[] {},
187 pnkfelix 1.1.2.10                                 new Temp[] { r, FP() }) });
188 pnkfelix 1.1.2.3          }
189 pnkfelix 1.1.2.3      }
190 pnkfelix 1.1.2.3  
191 pnkfelix 1.1.2.8      private String getWrappedAssem(String[] strs, int offset, String spStr) {
192 pnkfelix 1.1.2.3          String assem = "";
193 pnkfelix 1.1.2.3          int numSPdec = 0;
194 pnkfelix 1.1.2.3          while (offset >= OFFSET_LIMIT) {
195 pnkfelix 1.1.2.3              numSPdec++;
196 pnkfelix 1.1.2.4              // can only do eight-bit chunks in 2nd Operand
197 pnkfelix 1.1.2.4              int op2 = OFFSET_LIMIT*4;
198 pnkfelix 1.1.2.4              while(op2 != 0) {
199 pnkfelix 1.1.2.4                  // FSK: trusting CSA's code from CodeGen here...
200 pnkfelix 1.1.2.4                  int eight = op2 & (0xFF << ((Util.ffs(op2)-1) & ~1));
201 pnkfelix 1.1.2.8                  assem += "sub "+spStr+", "+spStr+", #"+eight+"\n";              
202 pnkfelix 1.1.2.4                  op2 ^= eight;
203 pnkfelix 1.1.2.4              }
204 pnkfelix 1.1.2.3              offset -= OFFSET_LIMIT;
205 pnkfelix 1.1.2.3          }
206 pnkfelix 1.1.2.3          
207 cananian 1.5              Iterator strIter = Arrays.asList(strs).iterator();
208 pnkfelix 1.1.2.3          while(strIter.hasNext()) { 
209 pnkfelix 1.1.2.3              assem += (String)strIter.next() +"\n"; 
210 pnkfelix 1.1.2.3          }
211 pnkfelix 1.1.2.3          
212 pnkfelix 1.1.2.3          while(numSPdec > 0) {
213 pnkfelix 1.1.2.3              numSPdec--;
214 pnkfelix 1.1.2.4              int op2 = OFFSET_LIMIT*4;
215 pnkfelix 1.1.2.4              while(op2 != 0) {
216 pnkfelix 1.1.2.4                  // FSK: symmetric with above code (sort of)
217 pnkfelix 1.1.2.4                  int eight = op2 & (0xFF << ((Util.ffs(op2)-1) & ~1));
218 pnkfelix 1.1.2.8                  assem += "add "+spStr+", "+spStr+", #"+eight;
219 pnkfelix 1.1.2.4                  op2 ^= eight;
220 pnkfelix 1.1.2.4                  if (numSPdec > 0 || op2 != 0) assem += "\n";
221 pnkfelix 1.1.2.4              }
222 pnkfelix 1.1.2.1          }
223 pnkfelix 1.1.2.3          
224 pnkfelix 1.1.2.3          return assem;
225 pnkfelix 1.1.2.1      }
226 pnkfelix 1.1.2.1  
227 pnkfelix 1.1.2.1      public InstrLABEL makeLabel(Instr template) {
228 pnkfelix 1.1.2.1          Label l = new Label();
229 kkz      1.1.2.9          InstrLABEL il = new InstrLABEL(template.getFactory(), 
230 kkz      1.1.2.9                                         template,
231 kkz      1.1.2.9                                         l.toString() + ":", l);
232 kkz      1.1.2.9          return il;
233 kkz      1.1.2.9      }
234 kkz      1.1.2.9  
235 kkz      1.1.2.9      /** Returns a new <code>InstrLABEL</code> for generating new
236 kkz      1.1.2.9          arbitrary code blocks to branch to.
237 kkz      1.1.2.9          @param template An <code>Instr</code> to base the generated
238 kkz      1.1.2.9                          <code>InstrLABEL</code>.
239 kkz      1.1.2.9                          <code>template</code> should be part of the
240 kkz      1.1.2.9                          instruction stream that the returned
241 kkz      1.1.2.9                          <code>InstrLABEL</code> is intended for. 
242 kkz      1.1.2.9      */
243 kkz      1.1.2.9      public InstrLABEL makeLabel(Label l, Instr template) {
244 pnkfelix 1.1.2.1          InstrLABEL il = new InstrLABEL(template.getFactory(), 
245 pnkfelix 1.1.2.1                                         template,
246 pnkfelix 1.1.2.1                                         l.toString() + ":", l);
247 pnkfelix 1.1.2.1          return il;
248 pnkfelix 1.1.2.1      }
249 cananian 1.2      }