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