this repo has no description
at trunk 922 lines 33 kB view raw
1/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */ 2// Copyright (c) 2013, the Dart project authors and Facebook, Inc. and its 3// affiliates. Please see the AUTHORS-Dart file for details. All rights 4// reserved. Use of this source code is governed by a BSD-style license that 5// can be found in the LICENSE-Dart file. 6 7#pragma once 8 9#include "assembler-utils.h" 10#include "globals.h" 11#include "utils.h" 12 13namespace py { 14namespace x64 { 15 16enum Register { 17 RAX = 0, 18 RCX = 1, 19 RDX = 2, 20 RBX = 3, 21 RSP = 4, 22 RBP = 5, 23 RSI = 6, 24 RDI = 7, 25 R8 = 8, 26 R9 = 9, 27 R10 = 10, 28 R11 = 11, 29 R12 = 12, 30 R13 = 13, 31 R14 = 14, 32 R15 = 15, 33 kNoRegister = -1, // Signals an illegal register. 34 kNumRegisters = 16, 35}; 36 37enum XmmRegister { 38 XMM0 = 0, 39 XMM1 = 1, 40 XMM2 = 2, 41 XMM3 = 3, 42 XMM4 = 4, 43 XMM5 = 5, 44 XMM6 = 6, 45 XMM7 = 7, 46 XMM8 = 8, 47 XMM9 = 9, 48 XMM10 = 10, 49 XMM11 = 11, 50 XMM12 = 12, 51 XMM13 = 13, 52 XMM14 = 14, 53 XMM15 = 15, 54 kNoXmmRegister = -1, // Signals an illegal register. 55 kNumXmmRegisters = 16, 56}; 57 58enum RexBits { 59 REX_NONE = 0, 60 REX_B = 1 << 0, 61 REX_X = 1 << 1, 62 REX_R = 1 << 2, 63 REX_W = 1 << 3, 64 REX_PREFIX = 1 << 6 65}; 66 67enum Prefix { 68 LOCK = 0xf0, 69 REPNZ = 0xf2, 70 REP = 0xf3, 71}; 72 73enum Condition { 74 // This weird name avoids conflicts with the OVERFLOW macro in math.h on some 75 // platforms. 76 YES_OVERFLOW = 0, 77 NOT_OVERFLOW = 1, 78 BELOW = 2, 79 ABOVE_EQUAL = 3, 80 EQUAL = 4, 81 NOT_EQUAL = 5, 82 BELOW_EQUAL = 6, 83 ABOVE = 7, 84 SIGN = 8, 85 NOT_SIGN = 9, 86 PARITY = 10, 87 NOT_PARITY = 11, 88 LESS = 12, 89 GREATER_EQUAL = 13, 90 LESS_EQUAL = 14, 91 GREATER = 15, 92 93 ZERO = EQUAL, 94 NOT_ZERO = NOT_EQUAL, 95 CARRY = BELOW, 96 NOT_CARRY = ABOVE_EQUAL, 97 PARITY_EVEN = PARITY, 98 PARITY_ODD = NOT_PARITY, 99 100 // Platform-independent variants declared for all platforms 101 UNSIGNED_LESS = BELOW, 102 UNSIGNED_LESS_EQUAL = BELOW_EQUAL, 103 UNSIGNED_GREATER = ABOVE, 104 UNSIGNED_GREATER_EQUAL = ABOVE_EQUAL, 105 106 INVALID_CONDITION = -1 107}; 108 109enum ScaleFactor { 110 TIMES_1 = 0, 111 TIMES_2 = 1, 112 TIMES_4 = 2, 113 TIMES_8 = 3, 114 TIMES_16 = 4, 115}; 116 117// The largest multibyte nop we will emit. This could go up to 15 if it 118// becomes important to us. 119const int kMaxNopSize = 8; 120 121class Immediate { 122 public: 123 explicit Immediate(int64_t value) : value_(value) {} 124 125 Immediate(const Immediate& other) : value_(other.value_) {} 126 127 int64_t value() const { return value_; } 128 129 bool isInt8() const { return Utils::fits<int8_t>(value_); } 130 bool isUint8() const { return Utils::fits<uint8_t>(value_); } 131 bool isInt16() const { return Utils::fits<int16_t>(value_); } 132 bool isUint16() const { return Utils::fits<uint16_t>(value_); } 133 bool isInt32() const { return Utils::fits<int32_t>(value_); } 134 bool isUint32() const { return Utils::fits<uint32_t>(value_); } 135 136 private: 137 const int64_t value_; 138}; 139 140class Operand { 141 public: 142 uint8_t rex() const { return rex_; } 143 144 uint8_t mod() const { return (encodingAt(0) >> 6) & 3; } 145 146 Register rm() const { 147 int rm_rex = (rex_ & REX_B) << 3; 148 return static_cast<Register>(rm_rex + (encodingAt(0) & 7)); 149 } 150 151 ScaleFactor scale() const { 152 return static_cast<ScaleFactor>((encodingAt(1) >> 6) & 3); 153 } 154 155 Register index() const { 156 int index_rex = (rex_ & REX_X) << 2; 157 return static_cast<Register>(index_rex + ((encodingAt(1) >> 3) & 7)); 158 } 159 160 Register base() const { 161 int base_rex = (rex_ & REX_B) << 3; 162 return static_cast<Register>(base_rex + (encodingAt(1) & 7)); 163 } 164 165 int8_t disp8() const { 166 DCHECK(length_ >= 2, "assert()"); 167 return static_cast<int8_t>(encoding_[length_ - 1]); 168 } 169 170 int32_t disp32() const { 171 DCHECK(length_ >= 5, "assert()"); 172 int32_t result; 173 std::memcpy(&result, &encoding_[length_ - 4], sizeof(result)); 174 return result; 175 } 176 177 Operand(const Operand& other) : length_(other.length_), rex_(other.rex_) { 178 std::memmove(&encoding_[0], &other.encoding_[0], other.length_); 179 } 180 181 Operand& operator=(const Operand& other) { 182 length_ = other.length_; 183 rex_ = other.rex_; 184 memmove(&encoding_[0], &other.encoding_[0], other.length_); 185 return *this; 186 } 187 188 bool operator==(const Operand& other) const { 189 if (length_ != other.length_) return false; 190 if (rex_ != other.rex_) return false; 191 for (uint8_t i = 0; i < length_; i++) { 192 if (encoding_[i] != other.encoding_[i]) return false; 193 } 194 return true; 195 } 196 197 protected: 198 Operand() : length_(0), rex_(REX_NONE) {} // Needed by subclass Address. 199 200 void setModRM(int mod, Register rm) { 201 DCHECK((mod & ~3) == 0, "assert()"); 202 if ((rm > 7) && !((rm == R12) && (mod != 3))) { 203 rex_ |= REX_B; 204 } 205 encoding_[0] = (mod << 6) | (rm & 7); 206 length_ = 1; 207 } 208 209 void setSIB(ScaleFactor scale, Register index, Register base) { 210 DCHECK(length_ == 1, "assert()"); 211 DCHECK((scale & ~3) == 0, "assert()"); 212 if (base > 7) { 213 DCHECK((rex_ & REX_B) == 0, 214 "assert()"); // Must not have REX.B already set. 215 rex_ |= REX_B; 216 } 217 if (index > 7) rex_ |= REX_X; 218 encoding_[1] = (scale << 6) | ((index & 7) << 3) | (base & 7); 219 length_ = 2; 220 } 221 222 void setDisp8(int8_t disp) { 223 DCHECK(length_ == 1 || length_ == 2, "assert()"); 224 encoding_[length_++] = static_cast<uint8_t>(disp); 225 } 226 227 void setDisp32(int32_t disp) { 228 DCHECK(length_ == 1 || length_ == 2, "assert()"); 229 memmove(&encoding_[length_], &disp, sizeof(disp)); 230 length_ += sizeof(disp); 231 } 232 233 private: 234 uint8_t length_; 235 uint8_t rex_; 236 uint8_t encoding_[6]; 237 238 explicit Operand(Register reg) : rex_(REX_NONE) { setModRM(3, reg); } 239 240 // Get the operand encoding byte at the given index. 241 uint8_t encodingAt(word index) const { 242 DCHECK_BOUND(index, length_); 243 return encoding_[index]; 244 } 245 246 // Returns whether or not this register is a direct register operand 247 // referencing a specific register. Used from the assembler to generate better 248 // encodings. 249 bool hasRegister(Register reg) const { 250 return isRegister() && this->reg() == reg; 251 } 252 253 // Returns whether or not this operand represents a direct register operand. 254 bool isRegister() const { 255 return (encodingAt(0) & 0xf8) == 0xc0; // mod bits of ModR/M 256 } 257 258 // Returns the register represented by the rm field of this operand. 259 Register reg() const { 260 DCHECK(isRegister(), "reg() called on non-register Operand"); 261 return static_cast<Register>( 262 (encodingAt(0) & 0x7) | // r/m bits of ModR/M 263 ((rex_ & REX_B) ? 0x4 : 0x0)); // REX.B extension 264 } 265 266 friend class Assembler; 267}; 268 269class Address : public Operand { 270 public: 271 Address(Register base, int32_t disp) { 272 if ((disp == 0) && ((base & 7) != RBP)) { 273 setModRM(0, base); 274 if ((base & 7) == RSP) { 275 setSIB(TIMES_1, RSP, base); 276 } 277 } else if (Utils::fits<int8_t>(disp)) { 278 setModRM(1, base); 279 if ((base & 7) == RSP) { 280 setSIB(TIMES_1, RSP, base); 281 } 282 setDisp8(disp); 283 } else { 284 setModRM(2, base); 285 if ((base & 7) == RSP) { 286 setSIB(TIMES_1, RSP, base); 287 } 288 setDisp32(disp); 289 } 290 } 291 292 Address(Register index, ScaleFactor scale, int32_t disp) { 293 DCHECK(index != RSP, "Illegal addressing mode"); 294 setModRM(0, RSP); 295 setSIB(scale, index, RBP); 296 setDisp32(disp); 297 } 298 299 Address(Register base, Register index, ScaleFactor scale, int32_t disp) { 300 DCHECK(index != RSP, "Illegal addressing mode"); 301 if ((disp == 0) && ((base & 7) != RBP)) { 302 setModRM(0, RSP); 303 setSIB(scale, index, base); 304 } else if (Utils::fits<int8_t>(disp)) { 305 setModRM(1, RSP); 306 setSIB(scale, index, base); 307 setDisp8(disp); 308 } else { 309 setModRM(2, RSP); 310 setSIB(scale, index, base); 311 setDisp32(disp); 312 } 313 } 314 315 Address(const Address& other) : Operand(other) {} 316 317 Address& operator=(const Address& other) { 318 Operand::operator=(other); 319 return *this; 320 } 321 322 static Address addressRIPRelative(int32_t disp) { 323 return Address(RIPRelativeDisp(disp)); 324 } 325 static Address addressBaseImm32(Register base, int32_t disp) { 326 return Address(base, disp, ForceDisp32{}); 327 } 328 329 private: 330 // Only used to invoke the alternate constructor below. 331 enum class ForceDisp32 {}; 332 333 Address(Register base, int32_t disp, ForceDisp32) { 334 setModRM(2, base); 335 if ((base & 7) == RSP) { 336 setSIB(TIMES_1, RSP, base); 337 } 338 setDisp32(disp); 339 } 340 341 struct RIPRelativeDisp { 342 explicit RIPRelativeDisp(int32_t disp) : disp_(disp) {} 343 const int32_t disp_; 344 }; 345 346 explicit Address(const RIPRelativeDisp& disp) { 347 setModRM(0, static_cast<Register>(0x5)); 348 setDisp32(disp.disp_); 349 } 350}; 351 352class Assembler { 353 public: 354 Assembler() = default; 355 356 static const bool kNearJump = true; 357 static const bool kFarJump = false; 358 359 word codeSize() const { return buffer_.size(); } 360 361 uword codeAddress(word offset) { return buffer_.address(offset); } 362 363 void finalizeInstructions(MemoryRegion instructions) { 364 buffer_.finalizeInstructions(instructions); 365 } 366 367 void call(Register reg) { emitUnaryL(reg, 0xff, 2); } 368 void call(Address address) { emitUnaryL(address, 0xff, 2); } 369 void call(Label* label); 370 371 void pushq(Register reg); 372 void pushq(Address address) { emitUnaryL(address, 0xff, 6); } 373 void pushq(Immediate imm); 374 375 void popq(Register reg); 376 void popq(Address address) { emitUnaryL(address, 0x8f, 0); } 377 378 void setcc(Condition condition, Register dst); 379 380#define X86_ZERO_OPERAND_1_BYTE_INSTRUCTIONS(F) \ 381 F(ret, 0xc3) \ 382 F(leave, 0xc9) \ 383 F(hlt, 0xf4) \ 384 F(cld, 0xfc) \ 385 F(std, 0xfd) \ 386 F(int3, 0xcc) \ 387 F(pushad, 0x60) \ 388 F(popad, 0x61) \ 389 F(pushfd, 0x9c) \ 390 F(popfd, 0x9d) \ 391 F(sahf, 0x9e) \ 392 F(cdq, 0x99) \ 393 F(fwait, 0x9b) \ 394 F(cmpsb, 0xa6) \ 395 F(cmpsl, 0xa7) 396 397#define X86_ALU_CODES(F) \ 398 F(and, 4) \ 399 F(or, 1) \ 400 F(xor, 6) \ 401 F(add, 0) \ 402 F(adc, 2) \ 403 F(sub, 5) \ 404 F(sbb, 3) \ 405 F(cmp, 7) 406 407#define XMM_ALU_CODES(F) \ 408 F(bad0, 0) \ 409 F(sqrt, 1) \ 410 F(rsqrt, 2) \ 411 F(rcp, 3) \ 412 F(and, 4) \ 413 F(bad1, 5) \ 414 F(or, 6) \ 415 F(xor, 7) \ 416 F(add, 8) \ 417 F(mul, 9) \ 418 F(bad2, 0xa) \ 419 F(bad3, 0xb) \ 420 F(sub, 0xc) \ 421 F(min, 0xd) \ 422 F(div, 0xe) \ 423 F(max, 0xf) 424 425// Table 3-1, first part 426#define XMM_CONDITIONAL_CODES(F) \ 427 F(eq, 0) \ 428 F(lt, 1) \ 429 F(le, 2) \ 430 F(unord, 3) \ 431 F(neq, 4) \ 432 F(nlt, 5) \ 433 F(nle, 6) \ 434 F(ord, 7) 435 436#define X86_CONDITIONAL_SUFFIXES(F) \ 437 F(o, YES_OVERFLOW) \ 438 F(no, NOT_OVERFLOW) \ 439 F(c, CARRY) \ 440 F(nc, NOT_CARRY) \ 441 F(z, ZERO) \ 442 F(nz, NOT_ZERO) \ 443 F(na, BELOW_EQUAL) \ 444 F(a, ABOVE) \ 445 F(s, SIGN) \ 446 F(ns, NOT_SIGN) \ 447 F(pe, PARITY_EVEN) \ 448 F(po, PARITY_ODD) \ 449 F(l, LESS) \ 450 F(ge, GREATER_EQUAL) \ 451 F(le, LESS_EQUAL) \ 452 F(g, GREATER) \ 453 /* Some alternative names */ \ 454 F(e, EQUAL) \ 455 F(ne, NOT_EQUAL) 456 457// Register-register, register-address and address-register instructions. 458#define RR(width, name, ...) \ 459 void name(Register dst, Register src) { emit##width(dst, src, __VA_ARGS__); } 460#define RA(width, name, ...) \ 461 void name(Register dst, Address src) { emit##width(dst, src, __VA_ARGS__); } 462#define AR(width, name, ...) \ 463 void name(Address dst, Register src) { emit##width(src, dst, __VA_ARGS__); } 464#define REGULAR_INSTRUCTION(name, ...) \ 465 RA(W, name##w, __VA_ARGS__) \ 466 RA(L, name##l, __VA_ARGS__) \ 467 RA(Q, name##q, __VA_ARGS__) \ 468 RR(W, name##w, __VA_ARGS__) \ 469 RR(L, name##l, __VA_ARGS__) \ 470 RR(Q, name##q, __VA_ARGS__) 471 REGULAR_INSTRUCTION(test, 0x85) 472 REGULAR_INSTRUCTION(xchg, 0x87) 473 REGULAR_INSTRUCTION(imul, 0xaf, 0x0f) 474 REGULAR_INSTRUCTION(bsr, 0xbd, 0x0f) 475#undef REGULAR_INSTRUCTION 476 RA(Q, movsxd, 0x63) 477 RR(Q, movsxd, 0x63) 478 AR(B, movb, 0x88) 479 AR(L, movl, 0x89) 480 AR(Q, movq, 0x89) 481 AR(W, movw, 0x89) 482 RA(B, movb, 0x8a) 483 RA(L, movl, 0x8b) 484 RA(Q, movq, 0x8b) 485 RR(L, movl, 0x8b) 486 RA(Q, leaq, 0x8d) 487 RA(L, leal, 0x8d) 488 AR(L, cmpxchgl, 0xb1, 0x0f) 489 AR(Q, cmpxchgq, 0xb1, 0x0f) 490 RA(L, cmpxchgl, 0xb1, 0x0f) 491 RA(Q, cmpxchgq, 0xb1, 0x0f) 492 RR(L, cmpxchgl, 0xb1, 0x0f) 493 RR(Q, cmpxchgq, 0xb1, 0x0f) 494 RA(L, movzbl, 0xb6, 0x0f) 495 RR(L, movzbl, 0xb6, 0x0f) 496 RA(Q, movzbq, 0xb6, 0x0f) 497 RR(Q, movzbq, 0xb6, 0x0f) 498 RA(Q, movzwq, 0xb7, 0x0f) 499 RR(Q, movzwq, 0xb7, 0x0f) 500 RA(Q, movsbq, 0xbe, 0x0f) 501 RR(Q, movsbq, 0xbe, 0x0f) 502 RA(Q, movswq, 0xbf, 0x0f) 503 RR(Q, movswq, 0xbf, 0x0f) 504#define DECLARE_CMOV(name, code) \ 505 RR(Q, cmov##name##q, 0x40 + code, 0x0f) \ 506 RR(L, cmov##name##l, 0x40 + code, 0x0f) \ 507 RA(Q, cmov##name##q, 0x40 + code, 0x0f) \ 508 RA(L, cmov##name##l, 0x40 + code, 0x0f) 509 X86_CONDITIONAL_SUFFIXES(DECLARE_CMOV) 510#undef DECLARE_CMOV 511#undef AA 512#undef RA 513#undef AR 514 515#define SIMPLE(name, ...) \ 516 void name() { emitSimple(__VA_ARGS__); } 517 SIMPLE(cpuid, 0x0f, 0xa2) 518 SIMPLE(fcos, 0xd9, 0xff) 519 SIMPLE(fincstp, 0xd9, 0xf7) 520 SIMPLE(fsin, 0xd9, 0xfe) 521#undef SIMPLE 522// XmmRegister operations with another register or an address. 523#define XX(width, name, ...) \ 524 void name(XmmRegister dst, XmmRegister src) { \ 525 emit##width(dst, src, __VA_ARGS__); \ 526 } 527#define XA(width, name, ...) \ 528 void name(XmmRegister dst, Address src) { \ 529 emit##width(dst, src, __VA_ARGS__); \ 530 } 531#define AX(width, name, ...) \ 532 void name(Address dst, XmmRegister src) { \ 533 emit##width(src, dst, __VA_ARGS__); \ 534 } 535 // We could add movupd here, but movups does the same and is shorter. 536 XA(L, movups, 0x10, 0x0f); 537 XA(L, movsd, 0x10, 0x0f, 0xf2) 538 XA(L, movss, 0x10, 0x0f, 0xf3) 539 AX(L, movups, 0x11, 0x0f); 540 AX(L, movsd, 0x11, 0x0f, 0xf2) 541 AX(L, movss, 0x11, 0x0f, 0xf3) 542 XX(L, movhlps, 0x12, 0x0f) 543 XX(L, unpcklps, 0x14, 0x0f) 544 XX(L, unpcklpd, 0x14, 0x0f, 0x66) 545 XX(L, unpckhps, 0x15, 0x0f) 546 XX(L, unpckhpd, 0x15, 0x0f, 0x66) 547 XX(L, movlhps, 0x16, 0x0f) 548 XX(L, movaps, 0x28, 0x0f) 549 XX(L, comisd, 0x2f, 0x0f, 0x66) 550#define DECLARE_XMM(name, code) \ 551 XX(L, name##ps, 0x50 + code, 0x0f) \ 552 XA(L, name##ps, 0x50 + code, 0x0f) \ 553 AX(L, name##ps, 0x50 + code, 0x0f) \ 554 XX(L, name##pd, 0x50 + code, 0x0f, 0x66) \ 555 XA(L, name##pd, 0x50 + code, 0x0f, 0x66) \ 556 AX(L, name##pd, 0x50 + code, 0x0f, 0x66) \ 557 XX(L, name##sd, 0x50 + code, 0x0f, 0xf2) \ 558 XA(L, name##sd, 0x50 + code, 0x0f, 0xf2) \ 559 AX(L, name##sd, 0x50 + code, 0x0f, 0xf2) \ 560 XX(L, name##ss, 0x50 + code, 0x0f, 0xf3) \ 561 XA(L, name##ss, 0x50 + code, 0x0f, 0xf3) \ 562 AX(L, name##ss, 0x50 + code, 0x0f, 0xf3) 563 XMM_ALU_CODES(DECLARE_XMM) 564#undef DECLARE_XMM 565 XX(L, cvtps2pd, 0x5a, 0x0f) 566 XX(L, cvtpd2ps, 0x5a, 0x0f, 0x66) 567 XX(L, cvtsd2ss, 0x5a, 0x0f, 0xf2) 568 XX(L, cvtss2sd, 0x5a, 0x0f, 0xf3) 569 XX(L, pxor, 0xef, 0x0f, 0x66) 570 XX(L, subpl, 0xfa, 0x0f, 0x66) 571 XX(L, addpl, 0xfe, 0x0f, 0x66) 572#undef XX 573#undef AX 574#undef XA 575 576#define DECLARE_CMPPS(name, code) \ 577 void cmpps##name(XmmRegister dst, XmmRegister src) { \ 578 emitL(dst, src, 0xc2, 0x0f); \ 579 AssemblerBuffer::EnsureCapacity ensured(&buffer_); \ 580 emitUint8(code); \ 581 } 582 XMM_CONDITIONAL_CODES(DECLARE_CMPPS) 583#undef DECLARE_CMPPS 584 585#define DECLARE_SIMPLE(name, opcode) \ 586 void name() { emitSimple(opcode); } 587 X86_ZERO_OPERAND_1_BYTE_INSTRUCTIONS(DECLARE_SIMPLE) 588#undef DECLARE_SIMPLE 589 590 void movl(Register dst, Immediate imm); 591 void movl(Address dst, Immediate imm); 592 593 void movb(Address dst, Immediate imm); 594 595 void movw(Register dst, Address src); 596 void movw(Address dst, Immediate imm); 597 598 // RIP-relative lea 599 void leaq(Register dst, Label* label); 600 void movq(Register dst, Immediate imm); 601 void movq(Address dst, Immediate imm); 602 603 // Destination and source are reversed for some reason. 604 void movq(Register dst, XmmRegister src) { 605 emitQ(src, dst, 0x7e, 0x0f, 0x66); 606 } 607 void movl(Register dst, XmmRegister src) { 608 emitL(src, dst, 0x7e, 0x0f, 0x66); 609 } 610 void movss(XmmRegister dst, XmmRegister src) { 611 emitL(src, dst, 0x11, 0x0f, 0xf3); 612 } 613 void movsd(XmmRegister dst, XmmRegister src) { 614 emitL(src, dst, 0x11, 0x0f, 0xf2); 615 } 616 617 // Use the reversed operand order and the 0x89 bytecode instead of the 618 // obvious 0x88 encoding for this some, because it is expected by gdb older 619 // than 7.3.1 when disassembling a function's prologue (movq rbp, rsp). 620 void movq(Register dst, Register src) { emitQ(src, dst, 0x89); } 621 622 void movq(XmmRegister dst, Register src) { 623 emitQ(dst, src, 0x6e, 0x0f, 0x66); 624 } 625 626 void movd(XmmRegister dst, Register src) { 627 emitL(dst, src, 0x6e, 0x0f, 0x66); 628 } 629 void cvtsi2sdq(XmmRegister dst, Register src) { 630 emitQ(dst, src, 0x2a, 0x0f, 0xf2); 631 } 632 void cvtsi2sdl(XmmRegister dst, Register src) { 633 emitL(dst, src, 0x2a, 0x0f, 0xf2); 634 } 635 void cvttsd2siq(Register dst, XmmRegister src) { 636 emitQ(dst, src, 0x2c, 0x0f, 0xf2); 637 } 638 void cvttsd2sil(Register dst, XmmRegister src) { 639 emitL(dst, src, 0x2c, 0x0f, 0xf2); 640 } 641 void movmskpd(Register dst, XmmRegister src) { 642 emitL(dst, src, 0x50, 0x0f, 0x66); 643 } 644 void movmskps(Register dst, XmmRegister src) { emitL(dst, src, 0x50, 0x0f); } 645 646 void movsb(); 647 void movsl(); 648 void movsq(); 649 void movsw(); 650 void repMovsb(); 651 void repMovsl(); 652 void repMovsq(); 653 void repMovsw(); 654 void repnzMovsb(); 655 void repnzMovsl(); 656 void repnzMovsq(); 657 void repnzMovsw(); 658 659 void btl(Register dst, Register src) { emitL(src, dst, 0xa3, 0x0f); } 660 void btq(Register dst, Register src) { emitQ(src, dst, 0xa3, 0x0f); } 661 662 void notps(XmmRegister dst, XmmRegister src); 663 void negateps(XmmRegister dst, XmmRegister src); 664 void absps(XmmRegister dst, XmmRegister src); 665 void zerowps(XmmRegister dst, XmmRegister src); 666 667 void set1ps(XmmRegister dst, Register tmp, Immediate imm); 668 void shufps(XmmRegister dst, XmmRegister src, Immediate mask); 669 670 void negatepd(XmmRegister dst, XmmRegister src); 671 void abspd(XmmRegister dst, XmmRegister src); 672 void shufpd(XmmRegister dst, XmmRegister src, Immediate mask); 673 674 enum RoundingMode { 675 kRoundToNearest = 0x0, 676 kRoundDown = 0x1, 677 kRoundUp = 0x2, 678 kRoundToZero = 0x3 679 }; 680 void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode); 681 682 void testb(Register dst, Register src); 683 void testb(Register reg, Immediate imm); 684 void testb(Address address, Immediate imm); 685 void testb(Address address, Register reg); 686 687 void testl(Register reg, Immediate imm) { testq(reg, imm); } 688 689 // TODO(T47100904): These functions will emit a testl or a testb when possible 690 // based on the value of `imm`. This behavior is desired in most cases, but 691 // probably belongs in a differently-named function. 692 void testq(Register reg, Immediate imm); 693 void testq(Address address, Immediate imm); 694 695 void shldq(Register dst, Register src, Register shifter) { 696 DCHECK(shifter == RCX, "assert()"); 697 emitQ(src, dst, 0xa5, 0x0f); 698 } 699 void shrdq(Register dst, Register src, Register shifter) { 700 DCHECK(shifter == RCX, "assert()"); 701 emitQ(src, dst, 0xad, 0x0f); 702 } 703 704#define DECLARE_ALU(op, c) \ 705 void op##w(Register dst, Register src) { emitW(dst, src, c * 8 + 3); } \ 706 void op##l(Register dst, Register src) { emitL(dst, src, c * 8 + 3); } \ 707 void op##q(Register dst, Register src) { emitQ(dst, src, c * 8 + 3); } \ 708 void op##w(Register dst, Address src) { emitW(dst, src, c * 8 + 3); } \ 709 void op##l(Register dst, Address src) { emitL(dst, src, c * 8 + 3); } \ 710 void op##q(Register dst, Address src) { emitQ(dst, src, c * 8 + 3); } \ 711 void op##w(Address dst, Register src) { emitW(src, dst, c * 8 + 1); } \ 712 void op##l(Address dst, Register src) { emitL(src, dst, c * 8 + 1); } \ 713 void op##q(Address dst, Register src) { emitQ(src, dst, c * 8 + 1); } \ 714 void op##l(Register dst, Immediate imm) { aluL(c, dst, imm); } \ 715 void op##q(Register dst, Immediate imm) { aluQ(c, c * 8 + 3, dst, imm); } \ 716 void op##b(Register dst, Immediate imm) { aluB(c, dst, imm); } \ 717 void op##b(Address dst, Immediate imm) { aluB(c, dst, imm); } \ 718 void op##w(Address dst, Immediate imm) { aluW(c, dst, imm); } \ 719 void op##l(Address dst, Immediate imm) { aluL(c, dst, imm); } \ 720 void op##q(Address dst, Immediate imm) { aluQ(c, c * 8 + 3, dst, imm); } 721 722 X86_ALU_CODES(DECLARE_ALU) 723 724#undef DECLARE_ALU 725#undef ALU_OPS 726 727 void cqo(); 728 729#define REGULAR_UNARY(name, opcode, modrm) \ 730 void name##q(Register reg) { emitUnaryQ(reg, opcode, modrm); } \ 731 void name##l(Register reg) { emitUnaryL(reg, opcode, modrm); } \ 732 void name##q(Address address) { emitUnaryQ(address, opcode, modrm); } \ 733 void name##l(Address address) { emitUnaryL(address, opcode, modrm); } 734 REGULAR_UNARY(not, 0xf7, 2) 735 REGULAR_UNARY(neg, 0xf7, 3) 736 REGULAR_UNARY(mul, 0xf7, 4) 737 REGULAR_UNARY(div, 0xf7, 6) 738 REGULAR_UNARY(idiv, 0xf7, 7) 739 REGULAR_UNARY(inc, 0xff, 0) 740 REGULAR_UNARY(dec, 0xff, 1) 741#undef REGULAR_UNARY 742 743 void imull(Register reg, Immediate imm); 744 void imulq(Register dst, Immediate imm); 745 746 void shll(Register reg, Immediate imm); 747 void shll(Register operand, Register shifter); 748 void shrl(Register reg, Immediate imm); 749 void shrl(Register operand, Register shifter); 750 void sarl(Register reg, Immediate imm); 751 void sarl(Register operand, Register shifter); 752 void shldl(Register dst, Register src, Immediate imm); 753 754 void shlq(Register reg, Immediate imm); 755 void shlq(Register operand, Register shifter); 756 void shrq(Register reg, Immediate imm); 757 void shrq(Register operand, Register shifter); 758 void sarq(Register reg, Immediate imm); 759 void sarq(Register operand, Register shifter); 760 void shldq(Register dst, Register src, Immediate imm); 761 762 void btq(Register base, int bit); 763 764 void enter(Immediate imm); 765 766 void fldl(Address src); 767 void fstpl(Address dst); 768 769 void ffree(word value); 770 771 // 'size' indicates size in bytes and must be in the range 1..8. 772 void nop(int size = 1); 773 774 // 'size' may be arbitrarily large, and multiple nops will be used if needed. 775 void nops(int size); 776 777 void ud2(); 778 779 void jcc(Condition condition, Label* label, bool near); 780 void jmp(Register reg) { emitUnaryL(reg, 0xff, 4); } 781 void jmp(Address address) { emitUnaryL(address, 0xff, 4); } 782 void jmp(Label* label, bool near); 783 784 void lockCmpxchgq(Address address, Register reg) { 785 emitUint8(LOCK); 786 cmpxchgq(address, reg); 787 } 788 789 void lockCmpxchgl(Address address, Register reg) { 790 emitUint8(LOCK); 791 cmpxchgl(address, reg); 792 } 793 794 void align(int alignment); 795 void bind(Label* label); 796 797 void comment(const char* format, ...); 798 799 // Debugging and bringup support. 800 void breakpoint() { int3(); } 801 802 static void initializeMemoryWithBreakpoints(uword data, word length); 803 804 private: 805 void aluB(uint8_t modrm_opcode, Register dst, Immediate imm); 806 void aluL(uint8_t modrm_opcode, Register dst, Immediate imm); 807 void aluB(uint8_t modrm_opcode, Address dst, Immediate imm); 808 void aluW(uint8_t modrm_opcode, Address dst, Immediate imm); 809 void aluL(uint8_t modrm_opcode, Address dst, Immediate imm); 810 void aluQ(uint8_t modrm_opcode, uint8_t opcode, Register dst, Immediate imm); 811 void aluQ(uint8_t modrm_opcode, uint8_t opcode, Address dst, Immediate imm); 812 813 void emitSimple(int opcode, int opcode2 = -1); 814 void emitUnaryQ(Register reg, int opcode, int modrm_code); 815 void emitUnaryL(Register reg, int opcode, int modrm_code); 816 void emitUnaryQ(Address address, int opcode, int modrm_code); 817 void emitUnaryL(Address address, int opcode, int modrm_code); 818 // The prefixes are in reverse order due to the rules of default arguments in 819 // C++. 820 void emitQ(int reg, Address address, int opcode, int prefix2 = -1, 821 int prefix1 = -1); 822 void emitL(int reg, Address address, int opcode, int prefix2 = -1, 823 int prefix1 = -1); 824 void emitB(Register reg, Address address, int opcode, int prefix2 = -1, 825 int prefix1 = -1); 826 void emitW(Register reg, Address address, int opcode, int prefix2 = -1, 827 int prefix1 = -1); 828 void emitQ(int dst, int src, int opcode, int prefix2 = -1, int prefix1 = -1); 829 void emitL(int dst, int src, int opcode, int prefix2 = -1, int prefix1 = -1); 830 void emitW(Register dst, Register src, int opcode, int prefix2 = -1, 831 int prefix1 = -1); 832 void cmpPS(XmmRegister dst, XmmRegister src, int condition); 833 void emitTestB(Operand operand, Immediate imm); 834 void emitTestQ(Operand operand, Immediate imm); 835 836 void emitUint8(uint8_t value); 837 void emitInt32(int32_t value); 838 void emitUInt32(uint32_t value); 839 void emitInt64(int64_t value); 840 841 static uint8_t byteRegisterREX(Register reg); 842 static uint8_t byteOperandREX(Operand operand); 843 844 void emitRegisterREX(Register reg, uint8_t rex); 845 void emitOperandREX(int rm, Operand operand, uint8_t rex); 846 void emitRegisterOperand(int rm, int reg); 847 void emitFixup(AssemblerFixup* fixup); 848 void emitOperandSizeOverride(); 849 void emitRegRegREX(int reg, int base, uint8_t rex = REX_NONE); 850 void emitOperand(int rm, Operand operand); 851 void emitImmediate(Immediate imm); 852 void emitComplexB(int rm, Operand operand, Immediate imm); 853 void emitComplex(int rm, Operand operand, Immediate immediate); 854 void emitSignExtendedInt8(int rm, Operand operand, Immediate immediate); 855 void emitLabel(Label* label, word instruction_size); 856 void emitLabelLink(Label* label); 857 void emitNearLabelLink(Label* label); 858 859 void emitGenericShift(bool wide, int rm, Register reg, Immediate imm); 860 void emitGenericShift(bool wide, int rm, Register operand, Register shifter); 861 862 AssemblerBuffer buffer_; // Contains position independent code. 863 CodeComments comments_; 864 865 DISALLOW_COPY_AND_ASSIGN(Assembler); 866}; 867 868inline void Assembler::emitUint8(uint8_t value) { 869 buffer_.emit<uint8_t>(value); 870} 871 872inline void Assembler::emitInt32(int32_t value) { 873 buffer_.emit<int32_t>(value); 874} 875 876inline void Assembler::emitUInt32(uint32_t value) { 877 buffer_.emit<uint32_t>(value); 878} 879 880inline void Assembler::emitInt64(int64_t value) { 881 buffer_.emit<int64_t>(value); 882} 883 884inline uint8_t Assembler::byteRegisterREX(Register reg) { 885 // SPL, BPL, SIL, or DIL require a REX prefix. 886 return reg >= RSP && reg <= RDI ? REX_PREFIX : REX_NONE; 887} 888 889inline uint8_t Assembler::byteOperandREX(Operand operand) { 890 return operand.isRegister() ? byteRegisterREX(operand.reg()) 891 : uint8_t{REX_NONE}; 892} 893 894inline void Assembler::emitRegisterREX(Register reg, uint8_t rex) { 895 DCHECK(reg != kNoRegister && reg <= R15, "assert()"); 896 DCHECK(rex == REX_NONE || rex == REX_W, "assert()"); 897 rex |= (reg > 7 ? REX_B : REX_NONE); 898 if (rex != REX_NONE) emitUint8(REX_PREFIX | rex); 899} 900 901inline void Assembler::emitOperandREX(int rm, Operand operand, uint8_t rex) { 902 rex |= (rm > 7 ? REX_R : REX_NONE) | operand.rex(); 903 if (rex != REX_NONE) emitUint8(REX_PREFIX | rex); 904} 905 906inline void Assembler::emitRegRegREX(int reg, int base, uint8_t rex) { 907 DCHECK(reg != kNoRegister && reg <= R15, "assert()"); 908 DCHECK(base != kNoRegister && base <= R15, "assert()"); 909 DCHECK(rex == REX_NONE || rex == REX_W || rex == REX_PREFIX, "assert()"); 910 if (reg > 7) rex |= REX_R; 911 if (base > 7) rex |= REX_B; 912 if (rex != REX_NONE) emitUint8(REX_PREFIX | rex); 913} 914 915inline void Assembler::emitFixup(AssemblerFixup* fixup) { 916 buffer_.emitFixup(fixup); 917} 918 919inline void Assembler::emitOperandSizeOverride() { emitUint8(0x66); } 920 921} // namespace x64 922} // namespace py