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