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