github.com/tencent/goom@v1.0.1/internal/arch/x86asm/inst.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 x86asm implements decoding of x86 machine code. 6 package x86asm 7 8 import ( 9 "bytes" 10 "fmt" 11 ) 12 13 // Inst is a single instruction. 14 type Inst struct { 15 Prefix Prefixes // Prefixes applied to the instruction. 16 Op Op // Opcode mnemonic 17 Opcode uint32 // Encoded opcode bits, left aligned (first byte is Opcode>>24, etc) 18 Args Args // Instruction arguments, in Intel order 19 Mode int // processor mode in bits: 16, 32, or 64 20 AddrSize int // address size in bits: 16, 32, or 64 21 DataSize int // operand size in bits: 16, 32, or 64 22 MemBytes int // size of memory argument in bytes: 1, 2, 4, 8, 16, and so on. 23 Len int // length of encoded instruction in bytes 24 PCRel int // length of PC-relative address in instruction encoding 25 PCRelOff int // index of start of PC-relative address in instruction encoding 26 } 27 28 // Prefixes is an array of prefixes associated with a single instruction. 29 // The prefixes are listed in the same order as found in the instruction: 30 // each prefix byte corresponds to one slot in the array. The first zero 31 // in the array marks the end of the prefixes. 32 type Prefixes [14]Prefix 33 34 // Prefix represents an Intel instruction prefix. 35 // The low 8 bits are the actual prefix byte encoding, 36 // and the top 8 bits contain distinguishing bits and metadata. 37 type Prefix uint16 38 39 // nolint 40 const ( 41 // Metadata about the role of a prefix in an instruction. 42 PrefixImplicit Prefix = 0x8000 // prefix is implied by instruction text 43 PrefixIgnored Prefix = 0x4000 // prefix is ignored: either irrelevant or overridden by a later prefix 44 PrefixInvalid Prefix = 0x2000 // prefix makes entire instruction invalid (bad LOCK) 45 46 // nolint 47 // Memory segment overrides. 48 PrefixES Prefix = 0x26 // ES segment override 49 PrefixCS Prefix = 0x2E // CS segment override 50 PrefixSS Prefix = 0x36 // SS segment override 51 PrefixDS Prefix = 0x3E // DS segment override 52 PrefixFS Prefix = 0x64 // FS segment override 53 PrefixGS Prefix = 0x65 // GS segment override 54 55 // PrefixPN Branch prediction. 56 PrefixPN Prefix = 0x12E // predict not taken (conditional branch only) 57 PrefixPT Prefix = 0x13E // predict taken (conditional branch only) 58 59 // nolint 60 // Size attributes. 61 PrefixDataSize Prefix = 0x66 // operand size override 62 PrefixData16 Prefix = 0x166 63 PrefixData32 Prefix = 0x266 64 PrefixAddrSize Prefix = 0x67 // address size override 65 PrefixAddr16 Prefix = 0x167 66 PrefixAddr32 Prefix = 0x267 67 68 // PrefixLOCK One of a kind. 69 PrefixLOCK Prefix = 0xF0 // lock 70 PrefixREPN Prefix = 0xF2 // repeat not zero 71 PrefixXACQUIRE Prefix = 0x1F2 72 PrefixBND Prefix = 0x2F2 73 PrefixREP Prefix = 0xF3 // repeat 74 PrefixXRELEASE Prefix = 0x1F3 75 76 // PrefixREX The REX prefixes must be in the range [PrefixREX, PrefixREX+0x10). 77 // the other bits are set or not according to the intended use. 78 PrefixREX Prefix = 0x40 // REX 64-bit extension prefix 79 PrefixREXW Prefix = 0x08 // extension bit W (64-bit instruction width) 80 PrefixREXR Prefix = 0x04 // extension bit R (r field in modrm) 81 PrefixREXX Prefix = 0x02 // extension bit X (index field in sib) 82 PrefixREXB Prefix = 0x01 // extension bit B (r/m field in modrm or base field in sib) 83 PrefixVEX2Bytes Prefix = 0xC5 // Short form of vex prefix 84 PrefixVEX3Bytes Prefix = 0xC4 // Long form of vex prefix 85 ) 86 87 // IsREX reports whether p is a REX prefix byte. 88 func (p Prefix) IsREX() bool { 89 return p&0xF0 == PrefixREX 90 } 91 92 // IsVEX reports whether p is a VEX prefix byte. 93 func (p Prefix) IsVEX() bool { 94 return p&0xFF == PrefixVEX2Bytes || p&0xFF == PrefixVEX3Bytes 95 } 96 97 // String to string 98 // nolint 99 func (p Prefix) String() string { 100 p &^= PrefixImplicit | PrefixIgnored | PrefixInvalid 101 if s := prefixNames[p]; s != "" { 102 return s 103 } 104 105 if p.IsREX() { 106 s := "REX." 107 if p&PrefixREXW != 0 { 108 s += "W" 109 } 110 111 if p&PrefixREXR != 0 { 112 s += "R" 113 } 114 115 if p&PrefixREXX != 0 { 116 s += "X" 117 } 118 119 if p&PrefixREXB != 0 { 120 s += "B" 121 } 122 123 return s 124 } 125 126 return fmt.Sprintf("Prefix(%#x)", int(p)) 127 } 128 129 // Op is an x86 opcode. 130 type Op uint32 131 132 // String to string 133 // noLint 134 func (op Op) String() string { 135 i := int(op) 136 if i < 0 || i >= len(opNames) || opNames[i] == "" { 137 return fmt.Sprintf("Op(%d)", i) 138 } 139 140 return opNames[i] 141 } 142 143 // Args holds the instruction arguments. 144 // If an instruction has fewer than 4 arguments, 145 // the final elements in the array are nil. 146 type Args [4]Arg 147 148 // Arg is a single instruction argument, 149 // one of these types: Reg, Mem, Imm, Rel. 150 type Arg interface { 151 // String to string 152 String() string 153 isArg() 154 } 155 156 // Note that the implements of Arg that follow are all sized 157 // so that on a 64-bit machine the data can be inlined in 158 // the interface value instead of requiring an allocation. 159 160 // Reg is a single register. 161 // The zero Reg value has no name but indicates “no register.” 162 type Reg uint8 163 164 // nolint 165 const ( 166 _ Reg = iota 167 168 // AL 8-bit 169 AL 170 CL 171 DL 172 BL 173 AH 174 CH 175 DH 176 BH 177 SPB 178 BPB 179 SIB 180 DIB 181 R8B 182 R9B 183 R10B 184 R11B 185 R12B 186 R13B 187 R14B 188 R15B 189 190 // AX 16-bit 191 AX 192 CX 193 DX 194 BX 195 SP 196 BP 197 SI 198 DI 199 R8W 200 R9W 201 R10W 202 R11W 203 R12W 204 R13W 205 R14W 206 R15W 207 208 // EAX 32-bit 209 EAX 210 ECX 211 EDX 212 EBX 213 ESP 214 EBP 215 ESI 216 EDI 217 R8L 218 R9L 219 R10L 220 R11L 221 R12L 222 R13L 223 R14L 224 R15L 225 226 // RAX 64-bit 227 RAX 228 RCX 229 RDX 230 RBX 231 RSP 232 RBP 233 RSI 234 RDI 235 R8 236 R9 237 R10 238 R11 239 R12 240 R13 241 R14 242 R15 243 244 // nolint 245 // Instruction pointer. 246 IP // 16-bit 247 EIP // 32-bit 248 RIP // 64-bit 249 250 // F0 387 floating point registers. 251 F0 252 F1 253 F2 254 F3 255 F4 256 F5 257 F6 258 F7 259 260 // nolint 261 // MMX registers. 262 M0 263 M1 264 M2 265 M3 266 M4 267 M5 268 M6 269 M7 270 271 // nolint 272 // XMM registers. 273 X0 274 X1 275 X2 276 X3 277 X4 278 X5 279 X6 280 X7 281 X8 282 X9 283 X10 284 X11 285 X12 286 X13 287 X14 288 X15 289 290 // nolint 291 // Segment registers. 292 ES 293 CS 294 SS 295 DS 296 FS 297 GS 298 299 // nolint 300 // System registers. 301 GDTR 302 IDTR 303 LDTR 304 MSW 305 TASK 306 307 // CR0 Control registers. 308 CR0 309 CR1 310 CR2 311 CR3 312 CR4 313 CR5 314 CR6 315 CR7 316 CR8 317 CR9 318 CR10 319 CR11 320 CR12 321 CR13 322 CR14 323 CR15 324 325 // DR0 Debug registers. 326 DR0 327 DR1 328 DR2 329 DR3 330 DR4 331 DR5 332 DR6 333 DR7 334 DR8 335 DR9 336 DR10 337 DR11 338 DR12 339 DR13 340 DR14 341 DR15 342 343 // TR0 Task registers. 344 TR0 345 TR1 346 TR2 347 TR3 348 TR4 349 TR5 350 TR6 351 TR7 352 ) 353 354 const regMax = TR7 355 356 // noLint 357 func (Reg) isArg() {} 358 359 // String to string 360 // noLint 361 func (r Reg) String() string { 362 i := int(r) 363 if i < 0 || i >= len(regNames) || regNames[i] == "" { 364 return fmt.Sprintf("Reg(%d)", i) 365 } 366 367 return regNames[i] 368 } 369 370 // Mem is a memory reference. 371 // The general form is Segment:[Base+Scale*Index+Disp]. 372 type Mem struct { 373 Segment Reg 374 Base Reg 375 Scale uint8 376 Index Reg 377 Disp int64 378 } 379 380 // noLint 381 func (Mem) isArg() {} 382 383 // String to string 384 // noLint 385 func (m Mem) String() string { 386 var base, plus, scale, index, disp string 387 388 if m.Base != 0 { 389 base = m.Base.String() 390 } 391 392 if m.Scale != 0 { 393 if m.Base != 0 { 394 plus = "+" 395 } 396 397 if m.Scale > 1 { 398 scale = fmt.Sprintf("%d*", m.Scale) 399 } 400 401 index = m.Index.String() 402 } 403 404 if m.Disp != 0 || m.Base == 0 && m.Scale == 0 { 405 disp = fmt.Sprintf("%+#x", m.Disp) 406 } 407 408 return "[" + base + plus + scale + index + disp + "]" 409 } 410 411 // Rel is an offset relative to the current instruction pointer. 412 type Rel int32 413 414 // noLint 415 func (Rel) isArg() {} 416 417 // String to string 418 // noLint 419 func (r Rel) String() string { 420 return fmt.Sprintf(".%+d", r) 421 } 422 423 // Imm is an integer constant. 424 type Imm int64 425 426 // noLint 427 func (Imm) isArg() {} 428 429 // String to string 430 // noLint 431 func (i Imm) String() string { 432 return fmt.Sprintf("%#x", int64(i)) 433 } 434 435 // String to strings 436 // noLint 437 func (i Inst) String() string { 438 var buf bytes.Buffer 439 440 for _, p := range i.Prefix { 441 if p == 0 { 442 break 443 } 444 445 if p&PrefixImplicit != 0 { 446 continue 447 } 448 449 fmt.Fprintf(&buf, "%v ", p) 450 } 451 452 fmt.Fprintf(&buf, "%v", i.Op) 453 454 sep := " " 455 456 for _, v := range i.Args { 457 if v == nil { 458 break 459 } 460 461 fmt.Fprintf(&buf, "%s%v", sep, v) 462 sep = ", " 463 } 464 465 return buf.String() 466 } 467 468 // noLint 469 func isMem(a Arg) bool { 470 _, ok := a.(Mem) 471 return ok 472 } 473 474 // The Op definitions and string list are in tables.go. 475 476 var prefixNames = map[Prefix]string{ 477 PrefixCS: "CS", 478 PrefixDS: "DS", 479 PrefixES: "ES", 480 PrefixFS: "FS", 481 PrefixGS: "GS", 482 PrefixSS: "SS", 483 PrefixLOCK: "LOCK", 484 PrefixREP: "REP", 485 PrefixREPN: "REPN", 486 PrefixAddrSize: "ADDRSIZE", 487 PrefixDataSize: "DATASIZE", 488 PrefixAddr16: "ADDR16", 489 PrefixData16: "DATA16", 490 PrefixAddr32: "ADDR32", 491 PrefixData32: "DATA32", 492 PrefixBND: "BND", 493 PrefixXACQUIRE: "XACQUIRE", 494 PrefixXRELEASE: "XRELEASE", 495 PrefixREX: "REX", 496 PrefixPT: "PT", 497 PrefixPN: "PN", 498 } 499 500 var regNames = [...]string{ 501 AL: "AL", 502 CL: "CL", 503 BL: "BL", 504 DL: "DL", 505 AH: "AH", 506 CH: "CH", 507 BH: "BH", 508 DH: "DH", 509 SPB: "SPB", 510 BPB: "BPB", 511 SIB: "SIB", 512 DIB: "DIB", 513 R8B: "R8B", 514 R9B: "R9B", 515 R10B: "R10B", 516 R11B: "R11B", 517 R12B: "R12B", 518 R13B: "R13B", 519 R14B: "R14B", 520 R15B: "R15B", 521 AX: "AX", 522 CX: "CX", 523 BX: "BX", 524 DX: "DX", 525 SP: "SP", 526 BP: "BP", 527 SI: "SI", 528 DI: "DI", 529 R8W: "R8W", 530 R9W: "R9W", 531 R10W: "R10W", 532 R11W: "R11W", 533 R12W: "R12W", 534 R13W: "R13W", 535 R14W: "R14W", 536 R15W: "R15W", 537 EAX: "EAX", 538 ECX: "ECX", 539 EDX: "EDX", 540 EBX: "EBX", 541 ESP: "ESP", 542 EBP: "EBP", 543 ESI: "ESI", 544 EDI: "EDI", 545 R8L: "R8L", 546 R9L: "R9L", 547 R10L: "R10L", 548 R11L: "R11L", 549 R12L: "R12L", 550 R13L: "R13L", 551 R14L: "R14L", 552 R15L: "R15L", 553 RAX: "RAX", 554 RCX: "RCX", 555 RDX: "RDX", 556 RBX: "RBX", 557 RSP: "RSP", 558 RBP: "RBP", 559 RSI: "RSI", 560 RDI: "RDI", 561 R8: "R8", 562 R9: "R9", 563 R10: "R10", 564 R11: "R11", 565 R12: "R12", 566 R13: "R13", 567 R14: "R14", 568 R15: "R15", 569 IP: "IP", 570 EIP: "EIP", 571 RIP: "RIP", 572 F0: "F0", 573 F1: "F1", 574 F2: "F2", 575 F3: "F3", 576 F4: "F4", 577 F5: "F5", 578 F6: "F6", 579 F7: "F7", 580 M0: "M0", 581 M1: "M1", 582 M2: "M2", 583 M3: "M3", 584 M4: "M4", 585 M5: "M5", 586 M6: "M6", 587 M7: "M7", 588 X0: "X0", 589 X1: "X1", 590 X2: "X2", 591 X3: "X3", 592 X4: "X4", 593 X5: "X5", 594 X6: "X6", 595 X7: "X7", 596 X8: "X8", 597 X9: "X9", 598 X10: "X10", 599 X11: "X11", 600 X12: "X12", 601 X13: "X13", 602 X14: "X14", 603 X15: "X15", 604 CS: "CS", 605 SS: "SS", 606 DS: "DS", 607 ES: "ES", 608 FS: "FS", 609 GS: "GS", 610 GDTR: "GDTR", 611 IDTR: "IDTR", 612 LDTR: "LDTR", 613 MSW: "MSW", 614 TASK: "TASK", 615 CR0: "CR0", 616 CR1: "CR1", 617 CR2: "CR2", 618 CR3: "CR3", 619 CR4: "CR4", 620 CR5: "CR5", 621 CR6: "CR6", 622 CR7: "CR7", 623 CR8: "CR8", 624 CR9: "CR9", 625 CR10: "CR10", 626 CR11: "CR11", 627 CR12: "CR12", 628 CR13: "CR13", 629 CR14: "CR14", 630 CR15: "CR15", 631 DR0: "DR0", 632 DR1: "DR1", 633 DR2: "DR2", 634 DR3: "DR3", 635 DR4: "DR4", 636 DR5: "DR5", 637 DR6: "DR6", 638 DR7: "DR7", 639 DR8: "DR8", 640 DR9: "DR9", 641 DR10: "DR10", 642 DR11: "DR11", 643 DR12: "DR12", 644 DR13: "DR13", 645 DR14: "DR14", 646 DR15: "DR15", 647 TR0: "TR0", 648 TR1: "TR1", 649 TR2: "TR2", 650 TR3: "TR3", 651 TR4: "TR4", 652 TR5: "TR5", 653 TR6: "TR6", 654 TR7: "TR7", 655 }