github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/cmd/compile/internal/ssa/gen/PPC64Ops.go (about) 1 // Copyright 2016 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 // +build ignore 6 7 package main 8 9 import "strings" 10 11 // Notes: 12 // - Less-than-64-bit integer types live in the low portion of registers. 13 // For now, the upper portion is junk; sign/zero-extension might be optimized in the future, but not yet. 14 // - Boolean types are zero or 1; stored in a byte, but loaded with AMOVBZ so the upper bytes of a register are zero. 15 // - *const instructions may use a constant larger than the instruction can encode. 16 // In this case the assembler expands to multiple instructions and uses tmp 17 // register (R31). 18 19 var regNamesPPC64 = []string{ 20 "R0", // REGZERO, not used, but simplifies counting in regalloc 21 "SP", // REGSP 22 "SB", // REGSB 23 "R3", 24 "R4", 25 "R5", 26 "R6", 27 "R7", 28 "R8", 29 "R9", 30 "R10", 31 "R11", // REGCTXT for closures 32 "R12", 33 "R13", // REGTLS 34 "R14", 35 "R15", 36 "R16", 37 "R17", 38 "R18", 39 "R19", 40 "R20", 41 "R21", 42 "R22", 43 "R23", 44 "R24", 45 "R25", 46 "R26", 47 "R27", 48 "R28", 49 "R29", 50 "g", // REGG. Using name "g" and setting Config.hasGReg makes it "just happen". 51 "R31", // REGTMP 52 53 "F0", 54 "F1", 55 "F2", 56 "F3", 57 "F4", 58 "F5", 59 "F6", 60 "F7", 61 "F8", 62 "F9", 63 "F10", 64 "F11", 65 "F12", 66 "F13", 67 "F14", 68 "F15", 69 "F16", 70 "F17", 71 "F18", 72 "F19", 73 "F20", 74 "F21", 75 "F22", 76 "F23", 77 "F24", 78 "F25", 79 "F26", 80 "F27", 81 "F28", 82 "F29", 83 "F30", 84 "F31", 85 86 // "CR0", 87 // "CR1", 88 // "CR2", 89 // "CR3", 90 // "CR4", 91 // "CR5", 92 // "CR6", 93 // "CR7", 94 95 // "CR", 96 // "XER", 97 // "LR", 98 // "CTR", 99 } 100 101 func init() { 102 // Make map from reg names to reg integers. 103 if len(regNamesPPC64) > 64 { 104 panic("too many registers") 105 } 106 num := map[string]int{} 107 for i, name := range regNamesPPC64 { 108 num[name] = i 109 } 110 buildReg := func(s string) regMask { 111 m := regMask(0) 112 for _, r := range strings.Split(s, " ") { 113 if n, ok := num[r]; ok { 114 m |= regMask(1) << uint(n) 115 continue 116 } 117 panic("register " + r + " not found") 118 } 119 return m 120 } 121 122 var ( 123 gp = buildReg("R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29") 124 fp = buildReg("F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26") 125 sp = buildReg("SP") 126 sb = buildReg("SB") 127 gr = buildReg("g") 128 // cr = buildReg("CR") 129 // ctr = buildReg("CTR") 130 // lr = buildReg("LR") 131 tmp = buildReg("R31") 132 ctxt = buildReg("R11") 133 // tls = buildReg("R13") 134 gp01 = regInfo{inputs: nil, outputs: []regMask{gp}} 135 gp11 = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}} 136 gp21 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp}} 137 gp1cr = regInfo{inputs: []regMask{gp | sp | sb}} 138 gp2cr = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}} 139 crgp = regInfo{inputs: nil, outputs: []regMask{gp}} 140 gpload = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}} 141 gpstore = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}} 142 gpstorezero = regInfo{inputs: []regMask{gp | sp | sb}} // ppc64.REGZERO is reserved zero value 143 fp01 = regInfo{inputs: nil, outputs: []regMask{fp}} 144 fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}} 145 fpgp = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}} 146 gpfp = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}} 147 fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}} 148 fp2cr = regInfo{inputs: []regMask{fp, fp}} 149 fpload = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{fp}} 150 fpstore = regInfo{inputs: []regMask{gp | sp | sb, fp}} 151 callerSave = regMask(gp | fp | gr) 152 ) 153 ops := []opData{ 154 {name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1 155 {name: "ADDconst", argLength: 1, reg: gp11, asm: "ADD", aux: "SymOff"}, // arg0 + auxInt + aux.(*gc.Sym) 156 {name: "FADD", argLength: 2, reg: fp21, asm: "FADD", commutative: true}, // arg0+arg1 157 {name: "FADDS", argLength: 2, reg: fp21, asm: "FADDS", commutative: true}, // arg0+arg1 158 {name: "SUB", argLength: 2, reg: gp21, asm: "SUB"}, // arg0-arg1 159 {name: "FSUB", argLength: 2, reg: fp21, asm: "FSUB"}, // arg0-arg1 160 {name: "FSUBS", argLength: 2, reg: fp21, asm: "FSUBS"}, // arg0-arg1 161 162 {name: "MULLD", argLength: 2, reg: gp21, asm: "MULLD", typ: "Int64", commutative: true}, // arg0*arg1 (signed 64-bit) 163 {name: "MULLW", argLength: 2, reg: gp21, asm: "MULLW", typ: "Int32", commutative: true}, // arg0*arg1 (signed 32-bit) 164 165 {name: "MULHD", argLength: 2, reg: gp21, asm: "MULHD", commutative: true}, // (arg0 * arg1) >> 64, signed 166 {name: "MULHW", argLength: 2, reg: gp21, asm: "MULHW", commutative: true}, // (arg0 * arg1) >> 32, signed 167 {name: "MULHDU", argLength: 2, reg: gp21, asm: "MULHDU", commutative: true}, // (arg0 * arg1) >> 64, unsigned 168 {name: "MULHWU", argLength: 2, reg: gp21, asm: "MULHWU", commutative: true}, // (arg0 * arg1) >> 32, unsigned 169 170 {name: "FMUL", argLength: 2, reg: fp21, asm: "FMUL", commutative: true}, // arg0*arg1 171 {name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true}, // arg0*arg1 172 173 {name: "SRAD", argLength: 2, reg: gp21, asm: "SRAD"}, // arg0 >>a arg1, 64 bits (all sign if arg1 & 64 != 0) 174 {name: "SRAW", argLength: 2, reg: gp21, asm: "SRAW"}, // arg0 >>a arg1, 32 bits (all sign if arg1 & 32 != 0) 175 {name: "SRD", argLength: 2, reg: gp21, asm: "SRD"}, // arg0 >> arg1, 64 bits (0 if arg1 & 64 != 0) 176 {name: "SRW", argLength: 2, reg: gp21, asm: "SRW"}, // arg0 >> arg1, 32 bits (0 if arg1 & 32 != 0) 177 {name: "SLD", argLength: 2, reg: gp21, asm: "SLD"}, // arg0 << arg1, 64 bits (0 if arg1 & 64 != 0) 178 {name: "SLW", argLength: 2, reg: gp21, asm: "SLW"}, // arg0 << arg1, 32 bits (0 if arg1 & 32 != 0) 179 180 {name: "ADDconstForCarry", argLength: 1, reg: regInfo{inputs: []regMask{gp | sp | sb}, clobbers: tmp}, aux: "Int16", asm: "ADDC", typ: "Flags"}, // _, carry := arg0 + aux 181 {name: "MaskIfNotCarry", argLength: 1, reg: crgp, asm: "ADDME", typ: "Int64"}, // carry - 1 (if carry then 0 else -1) 182 183 {name: "SRADconst", argLength: 1, reg: gp11, asm: "SRAD", aux: "Int64"}, // arg0 >>a aux, 64 bits 184 {name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "Int64"}, // arg0 >>a aux, 32 bits 185 {name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "Int64"}, // arg0 >> aux, 64 bits 186 {name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "Int64"}, // arg0 >> aux, 32 bits 187 {name: "SLDconst", argLength: 1, reg: gp11, asm: "SLD", aux: "Int64"}, // arg0 << aux, 64 bits 188 {name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "Int64"}, // arg0 << aux, 32 bits 189 190 {name: "FDIV", argLength: 2, reg: fp21, asm: "FDIV"}, // arg0/arg1 191 {name: "FDIVS", argLength: 2, reg: fp21, asm: "FDIVS"}, // arg0/arg1 192 193 {name: "DIVD", argLength: 2, reg: gp21, asm: "DIVD", typ: "Int64"}, // arg0/arg1 (signed 64-bit) 194 {name: "DIVW", argLength: 2, reg: gp21, asm: "DIVW", typ: "Int32"}, // arg0/arg1 (signed 32-bit) 195 {name: "DIVDU", argLength: 2, reg: gp21, asm: "DIVDU", typ: "Int64"}, // arg0/arg1 (unsigned 64-bit) 196 {name: "DIVWU", argLength: 2, reg: gp21, asm: "DIVWU", typ: "Int32"}, // arg0/arg1 (unsigned 32-bit) 197 198 // MOD is implemented as rem := arg0 - (arg0/arg1) * arg1 199 200 // Conversions are all float-to-float register operations. "Integer" refers to encoding in the FP register. 201 {name: "FCTIDZ", argLength: 1, reg: fp11, asm: "FCTIDZ", typ: "Float64"}, // convert float to 64-bit int round towards zero 202 {name: "FCTIWZ", argLength: 1, reg: fp11, asm: "FCTIWZ", typ: "Float64"}, // convert float to 32-bit int round towards zero 203 {name: "FCFID", argLength: 1, reg: fp11, asm: "FCFID", typ: "Float64"}, // convert 64-bit integer to float 204 {name: "FRSP", argLength: 1, reg: fp11, asm: "FRSP", typ: "Float64"}, // round float to 32-bit value 205 206 // Movement between float and integer registers with no change in bits; accomplished with stores+loads on PPC. 207 // Because the 32-bit load-literal-bits instructions have impoverished addressability, always widen the 208 // data instead and use FMOVDload and FMOVDstore instead (this will also dodge endianess issues). 209 // There are optimizations that should apply -- (Xi2f64 (MOVWload (not-ADD-ptr+offset) ) ) could use 210 // the word-load instructions. (Xi2f64 (MOVDload ptr )) can be (FMOVDload ptr) 211 212 {name: "Xf2i64", argLength: 1, reg: fpgp, typ: "Int64", usesScratch: true}, // move 64 bits of F register into G register 213 {name: "Xi2f64", argLength: 1, reg: gpfp, typ: "Float64", usesScratch: true}, // move 64 bits of G register into F register 214 215 {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0&arg1 216 {name: "ANDN", argLength: 2, reg: gp21, asm: "ANDN"}, // arg0&^arg1 217 {name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true}, // arg0|arg1 218 {name: "ORN", argLength: 2, reg: gp21, asm: "ORN"}, // arg0|^arg1 219 {name: "NOR", argLength: 2, reg: gp21, asm: "NOR"}, // ^(arg0|arg1) 220 {name: "XOR", argLength: 2, reg: gp21, asm: "XOR", typ: "Int64", commutative: true}, // arg0^arg1 221 {name: "EQV", argLength: 2, reg: gp21, asm: "EQV", typ: "Int64", commutative: true}, // arg0^^arg1 222 {name: "NEG", argLength: 1, reg: gp11, asm: "NEG"}, // -arg0 (integer) 223 {name: "FNEG", argLength: 1, reg: fp11, asm: "FNEG"}, // -arg0 (floating point) 224 {name: "FSQRT", argLength: 1, reg: fp11, asm: "FSQRT"}, // sqrt(arg0) (floating point) 225 {name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS"}, // sqrt(arg0) (floating point, single precision) 226 227 {name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int64"}, // arg0|aux 228 {name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64"}, // arg0^aux 229 {name: "ANDconst", argLength: 1, reg: regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}, asm: "ANDCC", aux: "Int64", clobberFlags: true}, // arg0&aux // and-immediate sets CC on PPC, always. 230 {name: "ANDCCconst", argLength: 1, reg: regInfo{inputs: []regMask{gp | sp | sb}}, asm: "ANDCC", aux: "Int64", typ: "Flags"}, // arg0&aux == 0 // and-immediate sets CC on PPC, always. 231 232 {name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB", typ: "Int64"}, // sign extend int8 to int64 233 {name: "MOVBZreg", argLength: 1, reg: gp11, asm: "MOVBZ", typ: "Int64"}, // zero extend uint8 to uint64 234 {name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVH", typ: "Int64"}, // sign extend int16 to int64 235 {name: "MOVHZreg", argLength: 1, reg: gp11, asm: "MOVHZ", typ: "Int64"}, // zero extend uint16 to uint64 236 {name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW", typ: "Int64"}, // sign extend int32 to int64 237 {name: "MOVWZreg", argLength: 1, reg: gp11, asm: "MOVWZ", typ: "Int64"}, // zero extend uint32 to uint64 238 {name: "MOVBZload", argLength: 2, reg: gpload, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true}, // zero extend uint8 to uint64 239 {name: "MOVHload", argLength: 2, reg: gpload, asm: "MOVH", aux: "SymOff", typ: "Int16", faultOnNilArg0: true}, // sign extend int16 to int64 240 {name: "MOVHZload", argLength: 2, reg: gpload, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true}, // zero extend uint16 to uint64 241 {name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVW", aux: "SymOff", typ: "Int32", faultOnNilArg0: true}, // sign extend int32 to int64 242 {name: "MOVWZload", argLength: 2, reg: gpload, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true}, // zero extend uint32 to uint64 243 {name: "MOVDload", argLength: 2, reg: gpload, asm: "MOVD", aux: "SymOff", typ: "Int64", faultOnNilArg0: true}, 244 245 {name: "FMOVDload", argLength: 2, reg: fpload, asm: "FMOVD", aux: "SymOff", typ: "Float64", faultOnNilArg0: true}, 246 {name: "FMOVSload", argLength: 2, reg: fpload, asm: "FMOVS", aux: "SymOff", typ: "Float32", faultOnNilArg0: true}, 247 {name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true}, 248 {name: "MOVHstore", argLength: 3, reg: gpstore, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true}, 249 {name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true}, 250 {name: "MOVDstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true}, 251 {name: "FMOVDstore", argLength: 3, reg: fpstore, asm: "FMOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true}, 252 {name: "FMOVSstore", argLength: 3, reg: fpstore, asm: "FMOVS", aux: "SymOff", typ: "Mem", faultOnNilArg0: true}, 253 254 {name: "MOVBstorezero", argLength: 2, reg: gpstorezero, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true}, // store zero byte to arg0+aux. arg1=mem 255 {name: "MOVHstorezero", argLength: 2, reg: gpstorezero, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true}, // store zero 2 bytes to ... 256 {name: "MOVWstorezero", argLength: 2, reg: gpstorezero, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true}, // store zero 4 bytes to ... 257 {name: "MOVDstorezero", argLength: 2, reg: gpstorezero, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true}, // store zero 8 bytes to ... 258 259 {name: "MOVDaddr", argLength: 1, reg: regInfo{inputs: []regMask{sp | sb}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVD", rematerializeable: true}, // arg0 + auxInt + aux.(*gc.Sym), arg0=SP/SB 260 261 {name: "MOVDconst", argLength: 0, reg: gp01, aux: "Int64", asm: "MOVD", typ: "Int64", rematerializeable: true}, // 262 {name: "FMOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "FMOVD", rematerializeable: true}, // 263 {name: "FMOVSconst", argLength: 0, reg: fp01, aux: "Float32", asm: "FMOVS", rematerializeable: true}, // 264 {name: "FCMPU", argLength: 2, reg: fp2cr, asm: "FCMPU", typ: "Flags"}, 265 266 {name: "CMP", argLength: 2, reg: gp2cr, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1 267 {name: "CMPU", argLength: 2, reg: gp2cr, asm: "CMPU", typ: "Flags"}, // arg0 compare to arg1 268 {name: "CMPW", argLength: 2, reg: gp2cr, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1 269 {name: "CMPWU", argLength: 2, reg: gp2cr, asm: "CMPWU", typ: "Flags"}, // arg0 compare to arg1 270 {name: "CMPconst", argLength: 1, reg: gp1cr, asm: "CMP", aux: "Int64", typ: "Flags"}, 271 {name: "CMPUconst", argLength: 1, reg: gp1cr, asm: "CMPU", aux: "Int64", typ: "Flags"}, 272 {name: "CMPWconst", argLength: 1, reg: gp1cr, asm: "CMPW", aux: "Int32", typ: "Flags"}, 273 {name: "CMPWUconst", argLength: 1, reg: gp1cr, asm: "CMPWU", aux: "Int32", typ: "Flags"}, 274 275 // pseudo-ops 276 {name: "Equal", argLength: 1, reg: crgp}, // bool, true flags encode x==y false otherwise. 277 {name: "NotEqual", argLength: 1, reg: crgp}, // bool, true flags encode x!=y false otherwise. 278 {name: "LessThan", argLength: 1, reg: crgp}, // bool, true flags encode x<y false otherwise. 279 {name: "FLessThan", argLength: 1, reg: crgp}, // bool, true flags encode x<y false otherwise. 280 {name: "LessEqual", argLength: 1, reg: crgp}, // bool, true flags encode x<=y false otherwise. 281 {name: "FLessEqual", argLength: 1, reg: crgp}, // bool, true flags encode x<=y false otherwise; PPC <= === !> which is wrong for NaN 282 {name: "GreaterThan", argLength: 1, reg: crgp}, // bool, true flags encode x>y false otherwise. 283 {name: "FGreaterThan", argLength: 1, reg: crgp}, // bool, true flags encode x>y false otherwise. 284 {name: "GreaterEqual", argLength: 1, reg: crgp}, // bool, true flags encode x>=y false otherwise. 285 {name: "FGreaterEqual", argLength: 1, reg: crgp}, // bool, true flags encode x>=y false otherwise.; PPC >= === !< which is wrong for NaN 286 287 // Scheduler ensures LoweredGetClosurePtr occurs only in entry block, 288 // and sorts it to the very beginning of the block to prevent other 289 // use of the closure pointer. 290 {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{ctxt}}}, 291 292 //arg0=ptr,arg1=mem, returns void. Faults if ptr is nil. 293 {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gp | sp | sb}, clobbers: tmp}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true}, 294 295 // Convert pointer to integer, takes a memory operand for ordering. 296 {name: "MOVDconvert", argLength: 2, reg: gp11, asm: "MOVD"}, 297 298 {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem 299 {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gp | sp, ctxt, 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem 300 {name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call deferproc. arg0=mem, auxint=argsize, returns mem 301 {name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call newproc. arg0=mem, auxint=argsize, returns mem 302 {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem 303 304 // large or unaligned zeroing 305 // arg0 = address of memory to zero (in R3, changed as side effect) 306 // arg1 = address of the last element to zero 307 // arg2 = mem 308 // returns mem 309 // ADD -8,R3,R3 // intermediate value not valid GC ptr, cannot expose to opt+GC 310 // MOVDU R0, 8(R3) 311 // CMP R3, Rarg1 312 // BLE -2(PC) 313 { 314 name: "LoweredZero", 315 aux: "Int64", 316 argLength: 3, 317 reg: regInfo{ 318 inputs: []regMask{buildReg("R3"), gp}, 319 clobbers: buildReg("R3"), 320 }, 321 clobberFlags: true, 322 typ: "Mem", 323 faultOnNilArg0: true, 324 }, 325 326 // large or unaligned move 327 // arg0 = address of dst memory (in R3, changed as side effect) 328 // arg1 = address of src memory (in R4, changed as side effect) 329 // arg2 = address of the last element of src 330 // arg3 = mem 331 // returns mem 332 // ADD -8,R3,R3 // intermediate value not valid GC ptr, cannot expose to opt+GC 333 // ADD -8,R4,R4 // intermediate value not valid GC ptr, cannot expose to opt+GC 334 // MOVDU 8(R4), Rtmp 335 // MOVDU Rtmp, 8(R3) 336 // CMP R4, Rarg2 337 // BLT -3(PC) 338 { 339 name: "LoweredMove", 340 aux: "Int64", 341 argLength: 4, 342 reg: regInfo{ 343 inputs: []regMask{buildReg("R3"), buildReg("R4"), gp}, 344 clobbers: buildReg("R3 R4"), 345 }, 346 clobberFlags: true, 347 typ: "Mem", 348 faultOnNilArg0: true, 349 faultOnNilArg1: true, 350 }, 351 352 // (InvertFlags (CMP a b)) == (CMP b a) 353 // So if we want (LessThan (CMP a b)) but we can't do that because a is a constant, 354 // then we do (LessThan (InvertFlags (CMP b a))) instead. 355 // Rewrites will convert this to (GreaterThan (CMP b a)). 356 // InvertFlags is a pseudo-op which can't appear in assembly output. 357 {name: "InvertFlags", argLength: 1}, // reverse direction of arg0 358 359 // Constant flag values. For any comparison, there are 3 possible 360 // outcomes: either the three from the signed total order (<,==,>) 361 // or the three from the unsigned total order, depending on which 362 // comparison operation was used (CMP or CMPU -- PPC is different from 363 // the other architectures, which have a single comparison producing 364 // both signed and unsigned comparison results.) 365 366 // These ops are for temporary use by rewrite rules. They 367 // cannot appear in the generated assembly. 368 {name: "FlagEQ"}, // equal 369 {name: "FlagLT"}, // signed < or unsigned < 370 {name: "FlagGT"}, // signed > or unsigned > 371 372 } 373 374 blocks := []blockData{ 375 {name: "EQ"}, 376 {name: "NE"}, 377 {name: "LT"}, 378 {name: "LE"}, 379 {name: "GT"}, 380 {name: "GE"}, 381 {name: "FLT"}, 382 {name: "FLE"}, 383 {name: "FGT"}, 384 {name: "FGE"}, 385 } 386 387 archs = append(archs, arch{ 388 name: "PPC64", 389 pkg: "cmd/internal/obj/ppc64", 390 genfile: "../../ppc64/ssa.go", 391 ops: ops, 392 blocks: blocks, 393 regnames: regNamesPPC64, 394 gpregmask: gp, 395 fpregmask: fp, 396 framepointerreg: int8(num["SP"]), 397 linkreg: -1, // not used 398 }) 399 }