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 }