github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/cmd/9g/prog.c (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include <u.h> 6 #include <libc.h> 7 #include "gg.h" 8 #include "opt.h" 9 10 enum { 11 LeftRdwr = LeftRead | LeftWrite, 12 RightRdwr = RightRead | RightWrite, 13 }; 14 15 // This table gives the basic information about instruction 16 // generated by the compiler and processed in the optimizer. 17 // See opt.h for bit definitions. 18 // 19 // Instructions not generated need not be listed. 20 // As an exception to that rule, we typically write down all the 21 // size variants of an operation even if we just use a subset. 22 // 23 // The table is formatted for 8-space tabs. 24 static ProgInfo progtable[ALAST] = { 25 [ATYPE]= {Pseudo | Skip}, 26 [ATEXT]= {Pseudo}, 27 [AFUNCDATA]= {Pseudo}, 28 [APCDATA]= {Pseudo}, 29 [AUNDEF]= {Break}, 30 [AUSEFIELD]= {OK}, 31 [ACHECKNIL]= {LeftRead}, 32 [AVARDEF]= {Pseudo | RightWrite}, 33 [AVARKILL]= {Pseudo | RightWrite}, 34 35 // NOP is an internal no-op that also stands 36 // for USED and SET annotations, not the Power opcode. 37 [ANOP]= {LeftRead | RightWrite}, 38 39 // Integer 40 [AADD]= {SizeQ | LeftRead | RegRead | RightWrite}, 41 [ASUB]= {SizeQ | LeftRead | RegRead | RightWrite}, 42 [ANEG]= {SizeQ | LeftRead | RegRead | RightWrite}, 43 [AAND]= {SizeQ | LeftRead | RegRead | RightWrite}, 44 [AOR]= {SizeQ | LeftRead | RegRead | RightWrite}, 45 [AXOR]= {SizeQ | LeftRead | RegRead | RightWrite}, 46 [AMULLD]= {SizeQ | LeftRead | RegRead | RightWrite}, 47 [AMULLW]= {SizeL | LeftRead | RegRead | RightWrite}, 48 [AMULHD]= {SizeL | LeftRead | RegRead | RightWrite}, 49 [AMULHDU]= {SizeL | LeftRead | RegRead | RightWrite}, 50 [ADIVD]= {SizeQ | LeftRead | RegRead | RightWrite}, 51 [ADIVDU]= {SizeQ | LeftRead | RegRead | RightWrite}, 52 [ASLD]= {SizeQ | LeftRead | RegRead | RightWrite}, 53 [ASRD]= {SizeQ | LeftRead | RegRead | RightWrite}, 54 [ASRAD]= {SizeQ | LeftRead | RegRead | RightWrite}, 55 [ACMP]= {SizeQ | LeftRead | RightRead}, 56 [ACMPU]= {SizeQ | LeftRead | RightRead}, 57 [ATD]= {SizeQ | RightRead}, 58 59 // Floating point. 60 [AFADD]= {SizeD | LeftRead | RegRead | RightWrite}, 61 [AFADDS]= {SizeF | LeftRead | RegRead | RightWrite}, 62 [AFSUB]= {SizeD | LeftRead | RegRead | RightWrite}, 63 [AFSUBS]= {SizeF | LeftRead | RegRead | RightWrite}, 64 [AFMUL]= {SizeD | LeftRead | RegRead | RightWrite}, 65 [AFMULS]= {SizeF | LeftRead | RegRead | RightWrite}, 66 [AFDIV]= {SizeD | LeftRead | RegRead | RightWrite}, 67 [AFDIVS]= {SizeF | LeftRead | RegRead | RightWrite}, 68 [AFCTIDZ]= {SizeF | LeftRead | RegRead | RightWrite}, 69 [AFCFID]= {SizeF | LeftRead | RegRead | RightWrite}, 70 [AFCMPU]= {SizeD | LeftRead | RightRead}, 71 [AFRSP]= {SizeD | LeftRead | RightWrite | Conv}, 72 73 // Moves 74 [AMOVB]= {SizeB | LeftRead | RightWrite | Move | Conv}, 75 [AMOVBU]= {SizeB | LeftRead | RightWrite | Move | Conv | PostInc}, 76 [AMOVBZ]= {SizeB | LeftRead | RightWrite | Move | Conv}, 77 [AMOVH]= {SizeW | LeftRead | RightWrite | Move | Conv}, 78 [AMOVHU]= {SizeW | LeftRead | RightWrite | Move | Conv | PostInc}, 79 [AMOVHZ]= {SizeW | LeftRead | RightWrite | Move | Conv}, 80 [AMOVW]= {SizeL | LeftRead | RightWrite | Move | Conv}, 81 // there is no AMOVWU. 82 [AMOVWZU]= {SizeL | LeftRead | RightWrite | Move | Conv | PostInc}, 83 [AMOVWZ]= {SizeL | LeftRead | RightWrite | Move | Conv}, 84 [AMOVD]= {SizeQ | LeftRead | RightWrite | Move}, 85 [AMOVDU]= {SizeQ | LeftRead | RightWrite | Move | PostInc}, 86 [AFMOVS]= {SizeF | LeftRead | RightWrite | Move | Conv}, 87 [AFMOVD]= {SizeD | LeftRead | RightWrite | Move}, 88 89 // Jumps 90 [ABR]= {Jump | Break}, 91 [ABL]= {Call}, 92 [ABEQ]= {Cjmp}, 93 [ABNE]= {Cjmp}, 94 [ABGE]= {Cjmp}, 95 [ABLT]= {Cjmp}, 96 [ABGT]= {Cjmp}, 97 [ABLE]= {Cjmp}, 98 [ARETURN]= {Break}, 99 100 [ADUFFZERO]= {Call}, 101 [ADUFFCOPY]= {Call}, 102 }; 103 104 static void 105 initproginfo(void) 106 { 107 static int initialized; 108 int addvariant[] = {V_CC, V_V, V_CC|V_V}; 109 int as, as2, i, variant; 110 111 if(initialized) 112 return; 113 initialized = 1; 114 115 // Perform one-time expansion of instructions in progtable to 116 // their CC, V, and VCC variants 117 for(as=0; as<nelem(progtable); as++) { 118 if(progtable[as].flags == 0) 119 continue; 120 variant = as2variant(as); 121 for(i=0; i<nelem(addvariant); i++) { 122 as2 = variant2as(as, variant | addvariant[i]); 123 if(as2 != 0 && progtable[as2].flags == 0) 124 progtable[as2] = progtable[as]; 125 } 126 } 127 } 128 129 void 130 proginfo(ProgInfo *info, Prog *p) 131 { 132 initproginfo(); 133 134 *info = progtable[p->as]; 135 if(info->flags == 0) { 136 *info = progtable[AADD]; 137 fatal("proginfo: unknown instruction %P", p); 138 } 139 140 if((info->flags & RegRead) && p->reg == NREG) { 141 info->flags &= ~RegRead; 142 info->flags |= /*CanRegRead |*/ RightRead; 143 } 144 145 if((p->from.type == D_OREG || p->from.type == D_CONST) && p->from.reg != NREG) { 146 info->regindex |= RtoB(p->from.reg); 147 if(info->flags & PostInc) { 148 info->regset |= RtoB(p->from.reg); 149 } 150 } 151 if((p->to.type == D_OREG || p->to.type == D_CONST) && p->to.reg != NREG) { 152 info->regindex |= RtoB(p->to.reg); 153 if(info->flags & PostInc) { 154 info->regset |= RtoB(p->to.reg); 155 } 156 } 157 158 if(p->from.type == D_CONST && p->from.sym != nil && (info->flags & LeftRead)) { 159 info->flags &= ~LeftRead; 160 info->flags |= LeftAddr; 161 } 162 163 if(p->as == ADUFFZERO) { 164 info->reguse |= (1<<D_R0) | RtoB(3); 165 info->regset |= RtoB(3); 166 } 167 if(p->as == ADUFFCOPY) { 168 // TODO(austin) Revisit when duffcopy is implemented 169 info->reguse |= RtoB(3) | RtoB(4) | RtoB(5); 170 info->regset |= RtoB(3) | RtoB(4); 171 } 172 } 173 174 // Instruction variants table. Initially this contains entries only 175 // for the "base" form of each instruction. On the first call to 176 // as2variant or variant2as, we'll add the variants to the table. 177 static int varianttable[ALAST][4] = { 178 [AADD]= {AADD, AADDCC, AADDV, AADDVCC}, 179 [AADDC]= {AADDC, AADDCCC, AADDCV, AADDCVCC}, 180 [AADDE]= {AADDE, AADDECC, AADDEV, AADDEVCC}, 181 [AADDME]= {AADDME, AADDMECC, AADDMEV, AADDMEVCC}, 182 [AADDZE]= {AADDZE, AADDZECC, AADDZEV, AADDZEVCC}, 183 [AAND]= {AAND, AANDCC, 0, 0}, 184 [AANDN]= {AANDN, AANDNCC, 0, 0}, 185 [ACNTLZD]= {ACNTLZD, ACNTLZDCC, 0, 0}, 186 [ACNTLZW]= {ACNTLZW, ACNTLZWCC, 0, 0}, 187 [ADIVD]= {ADIVD, ADIVDCC, ADIVDV, ADIVDVCC}, 188 [ADIVDU]= {ADIVDU, ADIVDUCC, ADIVDUV, ADIVDUVCC}, 189 [ADIVW]= {ADIVW, ADIVWCC, ADIVWV, ADIVWVCC}, 190 [ADIVWU]= {ADIVWU, ADIVWUCC, ADIVWUV, ADIVWUVCC}, 191 [AEQV]= {AEQV, AEQVCC, 0, 0}, 192 [AEXTSB]= {AEXTSB, AEXTSBCC, 0, 0}, 193 [AEXTSH]= {AEXTSH, AEXTSHCC, 0, 0}, 194 [AEXTSW]= {AEXTSW, AEXTSWCC, 0, 0}, 195 [AFABS]= {AFABS, AFABSCC, 0, 0}, 196 [AFADD]= {AFADD, AFADDCC, 0, 0}, 197 [AFADDS]= {AFADDS, AFADDSCC, 0, 0}, 198 [AFCFID]= {AFCFID, AFCFIDCC, 0, 0}, 199 [AFCTID]= {AFCTID, AFCTIDCC, 0, 0}, 200 [AFCTIDZ]= {AFCTIDZ, AFCTIDZCC, 0, 0}, 201 [AFCTIW]= {AFCTIW, AFCTIWCC, 0, 0}, 202 [AFCTIWZ]= {AFCTIWZ, AFCTIWZCC, 0, 0}, 203 [AFDIV]= {AFDIV, AFDIVCC, 0, 0}, 204 [AFDIVS]= {AFDIVS, AFDIVSCC, 0, 0}, 205 [AFMADD]= {AFMADD, AFMADDCC, 0, 0}, 206 [AFMADDS]= {AFMADDS, AFMADDSCC, 0, 0}, 207 [AFMOVD]= {AFMOVD, AFMOVDCC, 0, 0}, 208 [AFMSUB]= {AFMSUB, AFMSUBCC, 0, 0}, 209 [AFMSUBS]= {AFMSUBS, AFMSUBSCC, 0, 0}, 210 [AFMUL]= {AFMUL, AFMULCC, 0, 0}, 211 [AFMULS]= {AFMULS, AFMULSCC, 0, 0}, 212 [AFNABS]= {AFNABS, AFNABSCC, 0, 0}, 213 [AFNEG]= {AFNEG, AFNEGCC, 0, 0}, 214 [AFNMADD]= {AFNMADD, AFNMADDCC, 0, 0}, 215 [AFNMADDS]= {AFNMADDS, AFNMADDSCC, 0, 0}, 216 [AFNMSUB]= {AFNMSUB, AFNMSUBCC, 0, 0}, 217 [AFNMSUBS]= {AFNMSUBS, AFNMSUBSCC, 0, 0}, 218 [AFRES]= {AFRES, AFRESCC, 0, 0}, 219 [AFRSP]= {AFRSP, AFRSPCC, 0, 0}, 220 [AFRSQRTE]= {AFRSQRTE, AFRSQRTECC, 0, 0}, 221 [AFSEL]= {AFSEL, AFSELCC, 0, 0}, 222 [AFSQRT]= {AFSQRT, AFSQRTCC, 0, 0}, 223 [AFSQRTS]= {AFSQRTS, AFSQRTSCC, 0, 0}, 224 [AFSUB]= {AFSUB, AFSUBCC, 0, 0}, 225 [AFSUBS]= {AFSUBS, AFSUBSCC, 0, 0}, 226 [AMTFSB0]= {AMTFSB0, AMTFSB0CC, 0, 0}, 227 [AMTFSB1]= {AMTFSB1, AMTFSB1CC, 0, 0}, 228 [AMULHD]= {AMULHD, AMULHDCC, 0, 0}, 229 [AMULHDU]= {AMULHDU, AMULHDUCC, 0, 0}, 230 [AMULHW]= {AMULHW, AMULHWCC, 0, 0}, 231 [AMULHWU]= {AMULHWU, AMULHWUCC, 0, 0}, 232 [AMULLD]= {AMULLD, AMULLDCC, AMULLDV, AMULLDVCC}, 233 [AMULLW]= {AMULLW, AMULLWCC, AMULLWV, AMULLWVCC}, 234 [ANAND]= {ANAND, ANANDCC, 0, 0}, 235 [ANEG]= {ANEG, ANEGCC, ANEGV, ANEGVCC}, 236 [ANOR]= {ANOR, ANORCC, 0, 0}, 237 [AOR]= {AOR, AORCC, 0, 0}, 238 [AORN]= {AORN, AORNCC, 0, 0}, 239 [AREM]= {AREM, AREMCC, AREMV, AREMVCC}, 240 [AREMD]= {AREMD, AREMDCC, AREMDV, AREMDVCC}, 241 [AREMDU]= {AREMDU, AREMDUCC, AREMDUV, AREMDUVCC}, 242 [AREMU]= {AREMU, AREMUCC, AREMUV, AREMUVCC}, 243 [ARLDC]= {ARLDC, ARLDCCC, 0, 0}, 244 [ARLDCL]= {ARLDCL, ARLDCLCC, 0, 0}, 245 [ARLDCR]= {ARLDCR, ARLDCRCC, 0, 0}, 246 [ARLDMI]= {ARLDMI, ARLDMICC, 0, 0}, 247 [ARLWMI]= {ARLWMI, ARLWMICC, 0, 0}, 248 [ARLWNM]= {ARLWNM, ARLWNMCC, 0, 0}, 249 [ASLD]= {ASLD, ASLDCC, 0, 0}, 250 [ASLW]= {ASLW, ASLWCC, 0, 0}, 251 [ASRAD]= {ASRAD, ASRADCC, 0, 0}, 252 [ASRAW]= {ASRAW, ASRAWCC, 0, 0}, 253 [ASRD]= {ASRD, ASRDCC, 0, 0}, 254 [ASRW]= {ASRW, ASRWCC, 0, 0}, 255 [ASUB]= {ASUB, ASUBCC, ASUBV, ASUBVCC}, 256 [ASUBC]= {ASUBC, ASUBCCC, ASUBCV, ASUBCVCC}, 257 [ASUBE]= {ASUBE, ASUBECC, ASUBEV, ASUBEVCC}, 258 [ASUBME]= {ASUBME, ASUBMECC, ASUBMEV, ASUBMEVCC}, 259 [ASUBZE]= {ASUBZE, ASUBZECC, ASUBZEV, ASUBZEVCC}, 260 [AXOR]= {AXOR, AXORCC, 0, 0}, 261 }; 262 263 static void 264 initvariants(void) 265 { 266 static int initialized; 267 int i, j; 268 269 if(initialized) 270 return; 271 initialized = 1; 272 273 for(i=0; i<nelem(varianttable); i++) { 274 if(varianttable[i][0] == 0) { 275 // Instruction has no variants 276 varianttable[i][0] = i; 277 continue; 278 } 279 // Copy base form to other variants 280 if(varianttable[i][0] == i) { 281 for(j=0; j<nelem(varianttable[i]); j++) 282 memmove(&varianttable[varianttable[i][j]], &varianttable[i], sizeof(varianttable[i])); 283 } 284 } 285 } 286 287 // as2variant returns the variant (V_*) flags of instruction as. 288 int 289 as2variant(int as) 290 { 291 int i; 292 initvariants(); 293 for(i=0; i<nelem(varianttable[as]); i++) 294 if(varianttable[as][i] == as) 295 return i; 296 fatal("as2variant: instruction %A is not a variant of itself", as); 297 return 0; 298 } 299 300 // variant2as returns the instruction as with the given variant (V_*) flags. 301 // If no such variant exists, this returns 0. 302 int 303 variant2as(int as, int flags) 304 { 305 initvariants(); 306 return varianttable[as][flags]; 307 }