github.com/chenzhuoyu/iasm@v0.9.1/x86_64/encodings.go (about) 1 package x86_64 2 3 import ( 4 `encoding/binary` 5 `math` 6 ) 7 8 /** Operand Encoding Helpers **/ 9 10 func imml(v interface{}) byte { 11 return byte(toImmAny(v) & 0x0f) 12 } 13 14 func relv(v interface{}) int64 { 15 switch r := v.(type) { 16 case *Label : return 0 17 case RelativeOffset : return int64(r) 18 default : panic("invalid relative offset") 19 } 20 } 21 22 func addr(v interface{}) interface{} { 23 switch a := v.(*MemoryOperand).Addr; a.Type { 24 case Memory : return a.Memory 25 case Offset : return a.Offset 26 case Reference : return a.Reference 27 default : panic("invalid memory operand type") 28 } 29 } 30 31 func bcode(v interface{}) byte { 32 if m, ok := v.(*MemoryOperand); !ok { 33 panic("v is not a memory operand") 34 } else if m.Broadcast == 0 { 35 return 0 36 } else { 37 return 1 38 } 39 } 40 41 func vcode(v interface{}) byte { 42 switch r := v.(type) { 43 case XMMRegister : return byte(r) 44 case YMMRegister : return byte(r) 45 case ZMMRegister : return byte(r) 46 case MaskedRegister : return vcode(r.Reg) 47 default : panic("v is not a vector register") 48 } 49 } 50 51 func kcode(v interface{}) byte { 52 switch r := v.(type) { 53 case KRegister : return byte(r) 54 case XMMRegister : return 0 55 case YMMRegister : return 0 56 case ZMMRegister : return 0 57 case RegisterMask : return byte(r.K) 58 case MaskedRegister : return byte(r.Mask.K) 59 case *MemoryOperand : return toKcodeMem(r) 60 default : panic("v is not a maskable operand") 61 } 62 } 63 64 func zcode(v interface{}) byte { 65 switch r := v.(type) { 66 case KRegister : return 0 67 case XMMRegister : return 0 68 case YMMRegister : return 0 69 case ZMMRegister : return 0 70 case RegisterMask : return toZcodeRegM(r) 71 case MaskedRegister : return toZcodeRegM(r.Mask) 72 case *MemoryOperand : return toZcodeMem(r) 73 default : panic("v is not a maskable operand") 74 } 75 } 76 77 func lcode(v interface{}) byte { 78 switch r := v.(type) { 79 case Register8 : return byte(r & 0x07) 80 case Register16 : return byte(r & 0x07) 81 case Register32 : return byte(r & 0x07) 82 case Register64 : return byte(r & 0x07) 83 case KRegister : return byte(r & 0x07) 84 case MMRegister : return byte(r & 0x07) 85 case XMMRegister : return byte(r & 0x07) 86 case YMMRegister : return byte(r & 0x07) 87 case ZMMRegister : return byte(r & 0x07) 88 case MaskedRegister : return lcode(r.Reg) 89 default : panic("v is not a register") 90 } 91 } 92 93 func hcode(v interface{}) byte { 94 switch r := v.(type) { 95 case Register8 : return byte(r >> 3) & 1 96 case Register16 : return byte(r >> 3) & 1 97 case Register32 : return byte(r >> 3) & 1 98 case Register64 : return byte(r >> 3) & 1 99 case KRegister : return byte(r >> 3) & 1 100 case MMRegister : return byte(r >> 3) & 1 101 case XMMRegister : return byte(r >> 3) & 1 102 case YMMRegister : return byte(r >> 3) & 1 103 case ZMMRegister : return byte(r >> 3) & 1 104 case MaskedRegister : return hcode(r.Reg) 105 default : panic("v is not a register") 106 } 107 } 108 109 func ecode(v interface{}) byte { 110 switch r := v.(type) { 111 case Register8 : return byte(r >> 4) & 1 112 case Register16 : return byte(r >> 4) & 1 113 case Register32 : return byte(r >> 4) & 1 114 case Register64 : return byte(r >> 4) & 1 115 case KRegister : return byte(r >> 4) & 1 116 case MMRegister : return byte(r >> 4) & 1 117 case XMMRegister : return byte(r >> 4) & 1 118 case YMMRegister : return byte(r >> 4) & 1 119 case ZMMRegister : return byte(r >> 4) & 1 120 case MaskedRegister : return ecode(r.Reg) 121 default : panic("v is not a register") 122 } 123 } 124 125 func hlcode(v interface{}) byte { 126 switch r := v.(type) { 127 case Register8 : return toHLcodeReg8(r) 128 case Register16 : return byte(r & 0x0f) 129 case Register32 : return byte(r & 0x0f) 130 case Register64 : return byte(r & 0x0f) 131 case KRegister : return byte(r & 0x0f) 132 case MMRegister : return byte(r & 0x0f) 133 case XMMRegister : return byte(r & 0x0f) 134 case YMMRegister : return byte(r & 0x0f) 135 case ZMMRegister : return byte(r & 0x0f) 136 case MaskedRegister : return hlcode(r.Reg) 137 default : panic("v is not a register") 138 } 139 } 140 141 func ehcode(v interface{}) byte { 142 switch r := v.(type) { 143 case Register8 : return byte(r >> 3) & 0x03 144 case Register16 : return byte(r >> 3) & 0x03 145 case Register32 : return byte(r >> 3) & 0x03 146 case Register64 : return byte(r >> 3) & 0x03 147 case KRegister : return byte(r >> 3) & 0x03 148 case MMRegister : return byte(r >> 3) & 0x03 149 case XMMRegister : return byte(r >> 3) & 0x03 150 case YMMRegister : return byte(r >> 3) & 0x03 151 case ZMMRegister : return byte(r >> 3) & 0x03 152 case MaskedRegister : return ehcode(r.Reg) 153 default : panic("v is not a register") 154 } 155 } 156 157 func toImmAny(v interface{}) int64 { 158 if x, ok := asInt64(v); ok { 159 return x 160 } else { 161 panic("value is not an integer") 162 } 163 } 164 165 func toHcodeOpt(v interface{}) byte { 166 if v == nil { 167 return 0 168 } else { 169 return hcode(v) 170 } 171 } 172 173 func toEcodeVMM(v interface{}, x byte) byte { 174 switch r := v.(type) { 175 case XMMRegister : return ecode(r) 176 case YMMRegister : return ecode(r) 177 case ZMMRegister : return ecode(r) 178 default : return x 179 } 180 } 181 182 func toKcodeMem(v *MemoryOperand) byte { 183 if !v.Masked { 184 return 0 185 } else { 186 return byte(v.Mask.K) 187 } 188 } 189 190 func toZcodeMem(v *MemoryOperand) byte { 191 if !v.Masked || v.Mask.Z { 192 return 0 193 } else { 194 return 1 195 } 196 } 197 198 func toZcodeRegM(v RegisterMask) byte { 199 if v.Z { 200 return 1 201 } else { 202 return 0 203 } 204 } 205 206 func toHLcodeReg8(v Register8) byte { 207 switch v { 208 case AH: fallthrough 209 case BH: fallthrough 210 case CH: fallthrough 211 case DH: panic("ah/bh/ch/dh registers never use 4-bit encoding") 212 default: return byte(v & 0x0f) 213 } 214 } 215 216 /** Instruction Encoding Helpers **/ 217 218 const ( 219 _N_inst = 16 220 ) 221 222 const ( 223 _F_rel1 = 1 << iota 224 _F_rel4 225 ) 226 227 type _Encoding struct { 228 len int 229 flags int 230 bytes [_N_inst]byte 231 encoder func(m *_Encoding, v []interface{}) 232 } 233 234 // buf ensures len + n <= len(bytes). 235 func (self *_Encoding) buf(n int) []byte { 236 if i := self.len; i + n > _N_inst { 237 panic("instruction too long") 238 } else { 239 return self.bytes[i:] 240 } 241 } 242 243 // emit encodes a single byte. 244 func (self *_Encoding) emit(v byte) { 245 self.buf(1)[0] = v 246 self.len++ 247 } 248 249 // imm1 encodes a single byte immediate value. 250 func (self *_Encoding) imm1(v int64) { 251 self.emit(byte(v)) 252 } 253 254 // imm2 encodes a two-byte immediate value in little-endian. 255 func (self *_Encoding) imm2(v int64) { 256 binary.LittleEndian.PutUint16(self.buf(2), uint16(v)) 257 self.len += 2 258 } 259 260 // imm4 encodes a 4-byte immediate value in little-endian. 261 func (self *_Encoding) imm4(v int64) { 262 binary.LittleEndian.PutUint32(self.buf(4), uint32(v)) 263 self.len += 4 264 } 265 266 // imm8 encodes an 8-byte immediate value in little-endian. 267 func (self *_Encoding) imm8(v int64) { 268 binary.LittleEndian.PutUint64(self.buf(8), uint64(v)) 269 self.len += 8 270 } 271 272 // vex2 encodes a 2-byte or 3-byte VEX prefix. 273 // 274 // 2-byte VEX prefix: 275 // Requires: VEX.W = 0, VEX.mmmmm = 0b00001 and VEX.B = VEX.X = 0 276 // +----------------+ 277 // Byte 0: | Bits 0-7: 0xc5 | 278 // +----------------+ 279 // 280 // +-----------+----------------+----------+--------------+ 281 // Byte 1: | Bit 7: ~R | Bits 3-6 ~vvvv | Bit 2: L | Bits 0-1: pp | 282 // +-----------+----------------+----------+--------------+ 283 // 284 // 3-byte VEX prefix: 285 // +----------------+ 286 // Byte 0: | Bits 0-7: 0xc4 | 287 // +----------------+ 288 // 289 // +-----------+-----------+-----------+-------------------+ 290 // Byte 1: | Bit 7: ~R | Bit 6: ~X | Bit 5: ~B | Bits 0-4: 0b00001 | 291 // +-----------+-----------+-----------+-------------------+ 292 // 293 // +----------+-----------------+----------+--------------+ 294 // Byte 2: | Bit 7: 0 | Bits 3-6: ~vvvv | Bit 2: L | Bits 0-1: pp | 295 // +----------+-----------------+----------+--------------+ 296 // 297 func (self *_Encoding) vex2(lpp byte, r byte, rm interface{}, vvvv byte) { 298 var b byte 299 var x byte 300 301 /* VEX.R must be a single-bit mask */ 302 if r > 1 { 303 panic("VEX.R must be a 1-bit mask") 304 } 305 306 /* VEX.Lpp must be a 3-bit mask */ 307 if lpp &^ 0b111 != 0 { 308 panic("VEX.Lpp must be a 3-bit mask") 309 } 310 311 /* VEX.vvvv must be a 4-bit mask */ 312 if vvvv &^ 0b1111 != 0 { 313 panic("VEX.vvvv must be a 4-bit mask") 314 } 315 316 /* encode the RM bits if any */ 317 if rm != nil { 318 switch v := rm.(type) { 319 case *Label : break 320 case Register : b = hcode(v) 321 case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index) 322 case RelativeOffset : break 323 default : panic("rm is expected to be a register or a memory address") 324 } 325 } 326 327 /* if VEX.B and VEX.X are zeroes, 2-byte VEX prefix can be used */ 328 if x == 0 && b == 0 { 329 self.emit(0xc5) 330 self.emit(0xf8 ^ (r << 7) ^ (vvvv << 3) ^ lpp) 331 } else { 332 self.emit(0xc4) 333 self.emit(0xe1 ^ (r << 7) ^ (x << 6) ^ (b << 5)) 334 self.emit(0x78 ^ (vvvv << 3) ^ lpp) 335 } 336 } 337 338 // vex3 encodes a 3-byte VEX or XOP prefix. 339 // 340 // 3-byte VEX/XOP prefix 341 // +-----------------------------------+ 342 // Byte 0: | Bits 0-7: 0xc4 (VEX) / 0x8f (XOP) | 343 // +-----------------------------------+ 344 // 345 // +-----------+-----------+-----------+-----------------+ 346 // Byte 1: | Bit 7: ~R | Bit 6: ~X | Bit 5: ~B | Bits 0-4: mmmmm | 347 // +-----------+-----------+-----------+-----------------+ 348 // 349 // +----------+-----------------+----------+--------------+ 350 // Byte 2: | Bit 7: W | Bits 3-6: ~vvvv | Bit 2: L | Bits 0-1: pp | 351 // +----------+-----------------+----------+--------------+ 352 // 353 func (self *_Encoding) vex3(esc byte, mmmmm byte, wlpp byte, r byte, rm interface{}, vvvv byte) { 354 var b byte 355 var x byte 356 357 /* VEX.R must be a single-bit mask */ 358 if r > 1 { 359 panic("VEX.R must be a 1-bit mask") 360 } 361 362 /* VEX.vvvv must be a 4-bit mask */ 363 if vvvv &^ 0b1111 != 0 { 364 panic("VEX.vvvv must be a 4-bit mask") 365 } 366 367 /* escape must be a 3-byte VEX (0xc4) or XOP (0x8f) prefix */ 368 if esc != 0xc4 && esc != 0x8f { 369 panic("escape must be a 3-byte VEX (0xc4) or XOP (0x8f) prefix") 370 } 371 372 /* VEX.W____Lpp is expected to have no bits set except 0, 1, 2 and 7 */ 373 if wlpp &^ 0b10000111 != 0 { 374 panic("VEX.W____Lpp is expected to have no bits set except 0, 1, 2 and 7") 375 } 376 377 /* VEX.m-mmmm is expected to be a 5-bit mask */ 378 if mmmmm &^ 0b11111 != 0 { 379 panic("VEX.m-mmmm is expected to be a 5-bit mask") 380 } 381 382 /* encode the RM bits */ 383 switch v := rm.(type) { 384 case *Label : break 385 case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index) 386 case RelativeOffset : break 387 default : panic("rm is expected to be a register or a memory address") 388 } 389 390 /* encode the 3-byte VEX or XOP prefix */ 391 self.emit(esc) 392 self.emit(0xe0 ^ (r << 7) ^ (x << 6) ^ (b << 5) ^ mmmmm) 393 self.emit(0x78 ^ (vvvv << 3) ^ wlpp) 394 } 395 396 // evex encodes a 4-byte EVEX prefix. 397 func (self *_Encoding) evex(mm byte, w1pp byte, ll byte, rr byte, rm interface{}, vvvvv byte, aaa byte, zz byte, bb byte) { 398 var b byte 399 var x byte 400 401 /* EVEX.b must be a single-bit mask */ 402 if bb > 1 { 403 panic("EVEX.b must be a 1-bit mask") 404 } 405 406 /* EVEX.z must be a single-bit mask */ 407 if zz > 1 { 408 panic("EVEX.z must be a 1-bit mask") 409 } 410 411 /* EVEX.mm must be a 2-bit mask */ 412 if mm &^ 0b11 != 0 { 413 panic("EVEX.mm must be a 2-bit mask") 414 } 415 416 /* EVEX.L'L must be a 2-bit mask */ 417 if ll &^ 0b11 != 0 { 418 panic("EVEX.L'L must be a 2-bit mask") 419 } 420 421 /* EVEX.R'R must be a 2-bit mask */ 422 if rr &^ 0b11 != 0 { 423 panic("EVEX.R'R must be a 2-bit mask") 424 } 425 426 /* EVEX.aaa must be a 3-bit mask */ 427 if aaa &^ 0b111 != 0 { 428 panic("EVEX.aaa must be a 3-bit mask") 429 } 430 431 /* EVEX.v'vvvv must be a 5-bit mask */ 432 if vvvvv &^ 0b11111 != 0 { 433 panic("EVEX.v'vvvv must be a 5-bit mask") 434 } 435 436 /* EVEX.W____1pp is expected to have no bits set except 0, 1, 2, and 7 */ 437 if w1pp &^ 0b10000011 != 0b100 { 438 panic("EVEX.W____1pp is expected to have no bits set except 0, 1, 2, and 7") 439 } 440 441 /* extract bits from EVEX.R'R and EVEX.v'vvvv */ 442 r1, r0 := rr >> 1, rr & 1 443 v1, v0 := vvvvv >> 4, vvvvv & 0b1111 444 445 /* encode the RM bits if any */ 446 if rm != nil { 447 switch m := rm.(type) { 448 case *Label : break 449 case Register : b, x = hcode(m), ecode(m) 450 case MemoryAddress : b, x, v1 = toHcodeOpt(m.Base), toHcodeOpt(m.Index), toEcodeVMM(m.Index, v1) 451 case RelativeOffset : break 452 default : panic("rm is expected to be a register or a memory address") 453 } 454 } 455 456 /* EVEX prefix bytes */ 457 p0 := (r0 << 7) | (x << 6) | (b << 5) | (r1 << 4) | mm 458 p1 := (v0 << 3) | w1pp 459 p2 := (zz << 7) | (ll << 5) | (b << 4) | (v1 << 3) | aaa 460 461 /* p0: invert RXBR' (bits 4-7) 462 * p1: invert vvvv (bits 3-6) 463 * p2: invert V' (bit 3) */ 464 self.emit(0x62) 465 self.emit(p0 ^ 0xf0) 466 self.emit(p1 ^ 0x78) 467 self.emit(p2 ^ 0x08) 468 } 469 470 // rexm encodes a mandatory REX prefix. 471 func (self *_Encoding) rexm(w byte, r byte, rm interface{}) { 472 var b byte 473 var x byte 474 475 /* REX.R must be 0 or 1 */ 476 if r != 0 && r != 1 { 477 panic("REX.R must be 0 or 1") 478 } 479 480 /* REX.W must be 0 or 1 */ 481 if w != 0 && w != 1 { 482 panic("REX.W must be 0 or 1") 483 } 484 485 /* encode the RM bits */ 486 switch v := rm.(type) { 487 case *Label : break 488 case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index) 489 case RelativeOffset : break 490 default : panic("rm is expected to be a register or a memory address") 491 } 492 493 /* encode the REX prefix */ 494 self.emit(0x40 | (w << 3) | (r << 2) | (x << 1) | b) 495 } 496 497 // rexo encodes an optional REX prefix. 498 func (self *_Encoding) rexo(r byte, rm interface{}, force bool) { 499 var b byte 500 var x byte 501 502 /* REX.R must be 0 or 1 */ 503 if r != 0 && r != 1 { 504 panic("REX.R must be 0 or 1") 505 } 506 507 /* encode the RM bits */ 508 switch v := rm.(type) { 509 case *Label : break 510 case Register : b = hcode(v) 511 case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index) 512 case RelativeOffset : break 513 default : panic("rm is expected to be a register or a memory address") 514 } 515 516 /* if REX.R, REX.X, and REX.B are all zeroes, REX prefix can be omitted */ 517 if force || r != 0 || x != 0 || b != 0 { 518 self.emit(0x40 | (r << 2) | (x << 1) | b) 519 } 520 } 521 522 // mrsd encodes ModR/M, SIB and Displacement. 523 // 524 // ModR/M byte 525 // +----------------+---------------+---------------+ 526 // | Bits 6-7: Mode | Bits 3-5: Reg | Bits 0-2: R/M | 527 // +----------------+---------------+---------------+ 528 // 529 // SIB byte 530 // +-----------------+-----------------+----------------+ 531 // | Bits 6-7: Scale | Bits 3-5: Index | Bits 0-2: Base | 532 // +-----------------+-----------------+----------------+ 533 // 534 func (self *_Encoding) mrsd(reg byte, rm interface{}, disp8v int32) { 535 var ok bool 536 var mm MemoryAddress 537 var ro RelativeOffset 538 539 /* ModRM encodes the lower 3-bit of the register */ 540 if reg > 7 { 541 panic("invalid register bits") 542 } 543 544 /* check the displacement scale */ 545 switch disp8v { 546 case 1: break 547 case 2: break 548 case 4: break 549 case 8: break 550 case 16: break 551 case 32: break 552 case 64: break 553 default: panic("invalid displacement size") 554 } 555 556 /* special case: unresolved labels, assuming a zero offset */ 557 if _, ok = rm.(*Label); ok { 558 self.emit(0x05 | (reg << 3)) 559 self.imm4(0) 560 return 561 } 562 563 /* special case: RIP-relative offset 564 * ModRM.Mode == 0 and ModeRM.R/M == 5 indicates (rip + disp32) addressing */ 565 if ro, ok = rm.(RelativeOffset); ok { 566 self.emit(0x05 | (reg << 3)) 567 self.imm4(int64(ro)) 568 return 569 } 570 571 /* must be a generic memory address */ 572 if mm, ok = rm.(MemoryAddress); !ok { 573 panic("rm must be a memory address") 574 } 575 576 /* absolute addressing, encoded as disp(%rbp,%rsp,1) */ 577 if mm.Base == nil && mm.Index == nil { 578 self.emit(0x04 | (reg << 3)) 579 self.emit(0x25) 580 self.imm4(int64(mm.Displacement)) 581 return 582 } 583 584 /* no SIB byte */ 585 if mm.Index == nil && lcode(mm.Base) != 0b100 { 586 cc := lcode(mm.Base) 587 dv := mm.Displacement 588 589 /* ModRM.Mode == 0 (no displacement) */ 590 if dv == 0 && mm.Base != RBP && mm.Base != R13 { 591 if cc == 0b101 { 592 panic("rbp/r13 is not encodable as a base register (interpreted as disp32 address)") 593 } else { 594 self.emit((reg << 3) | cc) 595 return 596 } 597 } 598 599 /* ModRM.Mode == 1 (8-bit displacement) */ 600 if dq := dv / disp8v; dq >= math.MinInt8 && dq <= math.MaxInt8 && dv % disp8v == 0 { 601 self.emit(0x40 | (reg << 3) | cc) 602 self.imm1(int64(dq)) 603 return 604 } 605 606 /* ModRM.Mode == 2 (32-bit displacement) */ 607 self.emit(0x80 | (reg << 3) | cc) 608 self.imm4(int64(mm.Displacement)) 609 return 610 } 611 612 /* all encodings below use ModRM.R/M = 4 (0b100) to indicate the presence of SIB */ 613 if mm.Index == RSP { 614 panic("rsp is not encodable as an index register (interpreted as no index)") 615 } 616 617 /* index = 4 (0b100) denotes no-index encoding */ 618 var scale byte 619 var index byte = 0x04 620 621 /* encode the scale byte */ 622 if mm.Scale != 0 { 623 switch mm.Scale { 624 case 1 : scale = 0 625 case 2 : scale = 1 626 case 4 : scale = 2 627 case 8 : scale = 3 628 default : panic("invalid scale value") 629 } 630 } 631 632 /* encode the index byte */ 633 if mm.Index != nil { 634 index = lcode(mm.Index) 635 } 636 637 /* SIB.Base = 5 (0b101) and ModRM.Mode = 0 indicates no-base encoding with disp32 */ 638 if mm.Base == nil { 639 self.emit((reg << 3) | 0b100) 640 self.emit((scale << 6) | (index << 3) | 0b101) 641 self.imm4(int64(mm.Displacement)) 642 return 643 } 644 645 /* base L-code & displacement value */ 646 cc := lcode(mm.Base) 647 dv := mm.Displacement 648 649 /* ModRM.Mode == 0 (no displacement) */ 650 if dv == 0 && cc != 0b101 { 651 self.emit((reg << 3) | 0b100) 652 self.emit((scale << 6) | (index << 3) | cc) 653 return 654 } 655 656 /* ModRM.Mode == 1 (8-bit displacement) */ 657 if dq := dv / disp8v; dq >= math.MinInt8 && dq <= math.MaxInt8 && dv % disp8v == 0 { 658 self.emit(0x44 | (reg << 3)) 659 self.emit((scale << 6) | (index << 3) | cc) 660 self.imm1(int64(dq)) 661 return 662 } 663 664 /* ModRM.Mode == 2 (32-bit displacement) */ 665 self.emit(0x84 | (reg << 3)) 666 self.emit((scale << 6) | (index << 3) | cc) 667 self.imm4(int64(mm.Displacement)) 668 } 669 670 // encode invokes the encoder to encode this instruction. 671 func (self *_Encoding) encode(v []interface{}) int { 672 self.len = 0 673 self.encoder(self, v) 674 return self.len 675 }