github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/internal/obj/x86/evex.go (about) 1 // Copyright 2018 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.assembler file. 4 5 package x86 6 7 import ( 8 "github.com/Rookout/GoSDK/pkg/services/assembler/internal/obj" 9 "errors" 10 "fmt" 11 "strings" 12 ) 13 14 15 type evexBits struct { 16 b1 byte 17 b2 byte 18 19 20 opcode byte 21 } 22 23 24 func newEVEXBits(z int, enc *opBytes) evexBits { 25 return evexBits{ 26 b1: enc[z+0], 27 b2: enc[z+1], 28 opcode: enc[z+2], 29 } 30 } 31 32 33 func (evex evexBits) P() byte { return (evex.b1 & evexP) >> 0 } 34 35 36 func (evex evexBits) L() byte { return (evex.b1 & evexL) >> 2 } 37 38 39 func (evex evexBits) M() byte { return (evex.b1 & evexM) >> 4 } 40 41 42 func (evex evexBits) W() byte { return (evex.b1 & evexW) >> 7 } 43 44 45 func (evex evexBits) BroadcastEnabled() bool { 46 return evex.b2&evexBcst != 0 47 } 48 49 50 func (evex evexBits) ZeroingEnabled() bool { 51 return (evex.b2&evexZeroing)>>2 != 0 52 } 53 54 55 56 func (evex evexBits) RoundingEnabled() bool { 57 return (evex.b2&evexRounding)>>1 != 0 58 } 59 60 61 func (evex evexBits) SaeEnabled() bool { 62 return (evex.b2&evexSae)>>0 != 0 63 } 64 65 66 67 68 func (evex evexBits) DispMultiplier(bcst bool) int32 { 69 if bcst { 70 switch evex.b2 & evexBcst { 71 case evexBcstN4: 72 return 4 73 case evexBcstN8: 74 return 8 75 } 76 return 1 77 } 78 79 switch evex.b2 & evexN { 80 case evexN1: 81 return 1 82 case evexN2: 83 return 2 84 case evexN4: 85 return 4 86 case evexN8: 87 return 8 88 case evexN16: 89 return 16 90 case evexN32: 91 return 32 92 case evexN64: 93 return 64 94 case evexN128: 95 return 128 96 } 97 return 1 98 } 99 100 101 102 const ( 103 evexW = 0x80 104 evexWIG = 0 << 7 105 evexW0 = 0 << 7 106 evexW1 = 1 << 7 107 108 evexM = 0x30 109 evex0F = 1 << 4 110 evex0F38 = 2 << 4 111 evex0F3A = 3 << 4 112 113 evexL = 0x0C 114 evexLIG = 0 << 2 115 evex128 = 0 << 2 116 evex256 = 1 << 2 117 evex512 = 2 << 2 118 119 evexP = 0x03 120 evex66 = 1 << 0 121 evexF3 = 2 << 0 122 evexF2 = 3 << 0 123 124 125 126 127 evexN = 0xE0 128 evexN1 = 0 << 5 129 evexN2 = 1 << 5 130 evexN4 = 2 << 5 131 evexN8 = 3 << 5 132 evexN16 = 4 << 5 133 evexN32 = 5 << 5 134 evexN64 = 6 << 5 135 evexN128 = 7 << 5 136 137 138 evexBcst = 0x18 139 evexBcstN4 = 1 << 3 140 evexBcstN8 = 2 << 3 141 142 143 144 evexZeroing = 0x4 145 evexZeroingEnabled = 1 << 2 146 evexRounding = 0x2 147 evexRoundingEnabled = 1 << 1 148 evexSae = 0x1 149 evexSaeEnabled = 1 << 0 150 ) 151 152 153 func compressedDisp8(disp, elemSize int32) (disp8 byte, ok bool) { 154 if disp%elemSize == 0 { 155 v := disp / elemSize 156 if v >= -128 && v <= 127 { 157 return byte(v), true 158 } 159 } 160 return 0, false 161 } 162 163 164 func evexZcase(zcase uint8) bool { 165 return zcase > Zevex_first && zcase < Zevex_last 166 } 167 168 169 170 171 172 173 174 175 176 type evexSuffix struct { 177 rounding byte 178 sae bool 179 zeroing bool 180 broadcast bool 181 } 182 183 184 185 const ( 186 rcRNSAE = 0 187 rcRDSAE = 1 188 rcRUSAE = 2 189 rcRZSAE = 3 190 rcUnset = 4 191 ) 192 193 194 func newEVEXSuffix() evexSuffix { 195 return evexSuffix{rounding: rcUnset} 196 } 197 198 199 200 var evexSuffixMap [255]evexSuffix 201 202 func init() { 203 204 for i := range opSuffixTable { 205 suffix := newEVEXSuffix() 206 parts := strings.Split(opSuffixTable[i], ".") 207 for j := range parts { 208 switch parts[j] { 209 case "Z": 210 suffix.zeroing = true 211 case "BCST": 212 suffix.broadcast = true 213 case "SAE": 214 suffix.sae = true 215 216 case "RN_SAE": 217 suffix.rounding = rcRNSAE 218 case "RD_SAE": 219 suffix.rounding = rcRDSAE 220 case "RU_SAE": 221 suffix.rounding = rcRUSAE 222 case "RZ_SAE": 223 suffix.rounding = rcRZSAE 224 } 225 } 226 evexSuffixMap[i] = suffix 227 } 228 } 229 230 231 func toDisp8(disp int32, p *obj.Prog, asmbuf *AsmBuf) (disp8 byte, ok bool) { 232 if asmbuf.evexflag { 233 bcst := evexSuffixMap[p.Scond].broadcast 234 elemSize := asmbuf.evex.DispMultiplier(bcst) 235 return compressedDisp8(disp, elemSize) 236 } 237 return byte(disp), disp >= -128 && disp < 128 238 } 239 240 241 242 func EncodeRegisterRange(reg0, reg1 int16) int64 { 243 return (int64(reg0) << 0) | 244 (int64(reg1) << 16) | 245 obj.RegListX86Lo 246 } 247 248 249 func decodeRegisterRange(list int64) (reg0, reg1 int) { 250 return int((list >> 0) & 0xFFFF), 251 int((list >> 16) & 0xFFFF) 252 } 253 254 255 256 257 258 func ParseSuffix(p *obj.Prog, cond string) error { 259 cond = strings.TrimPrefix(cond, ".") 260 261 suffix := newOpSuffix(cond) 262 if !suffix.IsValid() { 263 return inferSuffixError(cond) 264 } 265 266 p.Scond = uint8(suffix) 267 return nil 268 } 269 270 271 272 273 274 275 276 277 278 279 280 281 func inferSuffixError(cond string) error { 282 suffixSet := make(map[string]bool) 283 unknownSet := make(map[string]bool) 284 hasBcst := false 285 hasRoundSae := false 286 var msg []string 287 288 suffixes := strings.Split(cond, ".") 289 for i, suffix := range suffixes { 290 switch suffix { 291 case "Z": 292 if i != len(suffixes)-1 { 293 msg = append(msg, "Z suffix should be the last") 294 } 295 case "BCST": 296 hasBcst = true 297 case "SAE", "RN_SAE", "RZ_SAE", "RD_SAE", "RU_SAE": 298 hasRoundSae = true 299 default: 300 if !unknownSet[suffix] { 301 msg = append(msg, fmt.Sprintf("unknown suffix %q", suffix)) 302 } 303 unknownSet[suffix] = true 304 } 305 306 if suffixSet[suffix] { 307 msg = append(msg, fmt.Sprintf("duplicate suffix %q", suffix)) 308 } 309 suffixSet[suffix] = true 310 } 311 312 if hasBcst && hasRoundSae { 313 msg = append(msg, "can't combine rounding/SAE and broadcast") 314 } 315 316 if len(msg) == 0 { 317 return errors.New("bad suffix combination") 318 } 319 return errors.New(strings.Join(msg, "; ")) 320 } 321 322 323 324 325 var opSuffixTable = [...]string{ 326 "", 327 328 "Z", 329 330 "SAE", 331 "SAE.Z", 332 333 "RN_SAE", 334 "RZ_SAE", 335 "RD_SAE", 336 "RU_SAE", 337 "RN_SAE.Z", 338 "RZ_SAE.Z", 339 "RD_SAE.Z", 340 "RU_SAE.Z", 341 342 "BCST", 343 "BCST.Z", 344 345 "<bad suffix>", 346 } 347 348 349 350 351 352 type opSuffix uint8 353 354 355 const badOpSuffix = opSuffix(len(opSuffixTable) - 1) 356 357 358 359 360 361 func newOpSuffix(suffixes string) opSuffix { 362 for i := range opSuffixTable { 363 if opSuffixTable[i] == suffixes { 364 return opSuffix(i) 365 } 366 } 367 return badOpSuffix 368 } 369 370 371 372 func (suffix opSuffix) IsValid() bool { 373 return suffix != badOpSuffix 374 } 375 376 377 378 379 380 381 func (suffix opSuffix) String() string { 382 return opSuffixTable[suffix] 383 }