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