this repo has no description
at trunk 968 lines 27 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#include "assembler-x64.h" 8 9#include <cstdarg> 10#include <cstdio> 11#include <cstring> 12 13#include "globals.h" 14 15namespace py { 16namespace x64 { 17 18void Assembler::initializeMemoryWithBreakpoints(uword data, word length) { 19 std::memset(reinterpret_cast<void*>(data), 0xcc, length); 20} 21 22void Assembler::call(Label* label) { 23 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 24 static const int size = 5; 25 emitUint8(0xe8); 26 emitLabel(label, size); 27} 28 29void Assembler::pushq(Register reg) { 30 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 31 emitRegisterREX(reg, REX_NONE); 32 emitUint8(0x50 | (reg & 7)); 33} 34 35void Assembler::pushq(Immediate imm) { 36 if (imm.isInt8()) { 37 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 38 emitUint8(0x6a); 39 emitUint8(imm.value() & 0xff); 40 } else { 41 DCHECK(imm.isInt32(), "assert()"); 42 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 43 emitUint8(0x68); 44 emitImmediate(imm); 45 } 46} 47 48void Assembler::popq(Register reg) { 49 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 50 emitRegisterREX(reg, REX_NONE); 51 emitUint8(0x58 | (reg & 7)); 52} 53 54void Assembler::setcc(Condition condition, Register dst) { 55 DCHECK(dst != kNoRegister, "assert()"); 56 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 57 if (dst >= 8) { 58 emitUint8(REX_PREFIX | (((dst & 0x08) != 0) ? REX_B : REX_NONE)); 59 } 60 emitUint8(0x0f); 61 emitUint8(0x90 + condition); 62 emitUint8(0xc0 + (dst & 0x07)); 63} 64 65void Assembler::emitQ(int reg, Address address, int opcode, int prefix2, 66 int prefix1) { 67 DCHECK(reg <= XMM15, "assert()"); 68 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 69 if (prefix1 >= 0) { 70 emitUint8(prefix1); 71 } 72 emitOperandREX(reg, address, REX_W); 73 if (prefix2 >= 0) { 74 emitUint8(prefix2); 75 } 76 emitUint8(opcode); 77 emitOperand(reg & 7, address); 78} 79 80void Assembler::emitB(Register reg, Address address, int opcode, int prefix2, 81 int prefix1) { 82 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 83 if (prefix1 >= 0) { 84 emitUint8(prefix1); 85 } 86 emitOperandREX(reg, address, byteRegisterREX(reg)); 87 if (prefix2 >= 0) { 88 emitUint8(prefix2); 89 } 90 emitUint8(opcode); 91 emitOperand(reg & 7, address); 92} 93 94void Assembler::emitL(int reg, Address address, int opcode, int prefix2, 95 int prefix1) { 96 DCHECK(reg <= XMM15, "assert()"); 97 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 98 if (prefix1 >= 0) { 99 emitUint8(prefix1); 100 } 101 emitOperandREX(reg, address, REX_NONE); 102 if (prefix2 >= 0) { 103 emitUint8(prefix2); 104 } 105 emitUint8(opcode); 106 emitOperand(reg & 7, address); 107} 108 109void Assembler::emitW(Register reg, Address address, int opcode, int prefix2, 110 int prefix1) { 111 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 112 if (prefix1 >= 0) { 113 emitUint8(prefix1); 114 } 115 emitOperandSizeOverride(); 116 emitOperandREX(reg, address, REX_NONE); 117 if (prefix2 >= 0) { 118 emitUint8(prefix2); 119 } 120 emitUint8(opcode); 121 emitOperand(reg & 7, address); 122} 123 124void Assembler::movl(Register dst, Immediate imm) { 125 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 126 Operand operand(dst); 127 emitOperandREX(0, operand, REX_NONE); 128 emitUint8(0xc7); 129 emitOperand(0, operand); 130 DCHECK(imm.isInt32(), "assert()"); 131 emitImmediate(imm); 132} 133 134void Assembler::movl(Address dst, Immediate imm) { 135 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 136 Operand operand(dst); 137 emitOperandREX(0, dst, REX_NONE); 138 emitUint8(0xc7); 139 emitOperand(0, dst); 140 DCHECK(imm.isInt32(), "assert()"); 141 emitImmediate(imm); 142} 143 144void Assembler::movb(Address dst, Immediate imm) { 145 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 146 emitOperandREX(0, dst, REX_NONE); 147 emitUint8(0xc6); 148 emitOperand(0, dst); 149 DCHECK(imm.isInt8(), "assert()"); 150 emitUint8(imm.value() & 0xff); 151} 152 153void Assembler::movw(Register /*dst*/, Address /*src*/) { 154 UNIMPLEMENTED("Use movzxw or movsxw instead."); 155} 156 157void Assembler::movw(Address dst, Immediate imm) { 158 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 159 emitOperandSizeOverride(); 160 emitOperandREX(0, dst, REX_NONE); 161 emitUint8(0xc7); 162 emitOperand(0, dst); 163 emitUint8(imm.value() & 0xff); 164 emitUint8((imm.value() >> 8) & 0xff); 165} 166 167void Assembler::leaq(Register dst, Label* label) { 168 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 169 // Emit RIP-relative lea 170 emitUint8(REX_PREFIX | REX_W | (dst > 7 ? REX_R : REX_NONE)); 171 emitUint8(0x8d); 172 Address address(Address::addressRIPRelative(0xdeadbeef)); 173 emitOperand(dst & 7, address); 174 // Overwrite the fake displacement with a label or label link 175 buffer_.remit<uint32_t>(); 176 static const int size = 7; 177 emitLabel(label, size); 178} 179 180void Assembler::movq(Register dst, Immediate imm) { 181 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 182 if (imm.isUint32()) { 183 // Pick single byte B8 encoding if possible. If dst < 8 then we also omit 184 // the Rex byte. 185 emitRegisterREX(dst, REX_NONE); 186 emitUint8(0xb8 | (dst & 7)); 187 emitUInt32(imm.value()); 188 } else if (imm.isInt32()) { 189 // Sign extended C7 Cx encoding if we have a negative input. 190 Operand operand(dst); 191 emitOperandREX(0, operand, REX_W); 192 emitUint8(0xc7); 193 emitOperand(0, operand); 194 emitImmediate(imm); 195 } else { 196 // Full 64 bit immediate encoding. 197 emitRegisterREX(dst, REX_W); 198 emitUint8(0xb8 | (dst & 7)); 199 emitImmediate(imm); 200 } 201} 202 203void Assembler::movq(Address dst, Immediate imm) { 204 CHECK(imm.isInt32(), "this instruction only exists for 32bit immediates"); 205 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 206 emitOperandREX(0, dst, REX_W); 207 emitUint8(0xC7); 208 emitOperand(0, dst); 209 emitImmediate(imm); 210} 211 212void Assembler::movsb() { 213 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 214 emitUint8(0xa4); 215} 216 217void Assembler::movsw() { 218 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 219 emitOperandSizeOverride(); 220 emitUint8(0xa5); 221} 222 223void Assembler::movsl() { 224 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 225 emitUint8(0xa5); 226} 227 228void Assembler::movsq() { 229 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 230 emitUint8(REX_PREFIX | REX_W); 231 emitUint8(0xa5); 232} 233 234void Assembler::repMovsb() { 235 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 236 emitUint8(REP); 237 emitUint8(0xa4); 238} 239 240void Assembler::repMovsw() { 241 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 242 emitUint8(REP); 243 emitOperandSizeOverride(); 244 emitUint8(0xa5); 245} 246 247void Assembler::repMovsl() { 248 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 249 emitUint8(REP); 250 emitUint8(0xa5); 251} 252 253void Assembler::repMovsq() { 254 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 255 emitUint8(REP); 256 emitUint8(REX_PREFIX | REX_W); 257 emitUint8(0xa5); 258} 259 260void Assembler::repnzMovsb() { 261 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 262 emitUint8(REPNZ); 263 emitUint8(0xa4); 264} 265 266void Assembler::repnzMovsw() { 267 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 268 emitUint8(REPNZ); 269 emitOperandSizeOverride(); 270 emitUint8(0xa5); 271} 272 273void Assembler::repnzMovsl() { 274 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 275 emitUint8(REPNZ); 276 emitUint8(0xa5); 277} 278 279void Assembler::repnzMovsq() { 280 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 281 emitUint8(REPNZ); 282 emitUint8(REX_PREFIX | REX_W); 283 emitUint8(0xa5); 284} 285 286void Assembler::emitSimple(int opcode, int opcode2) { 287 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 288 emitUint8(opcode); 289 if (opcode2 != -1) { 290 emitUint8(opcode2); 291 } 292} 293 294void Assembler::emitQ(int dst, int src, int opcode, int prefix2, int prefix1) { 295 DCHECK(src <= XMM15, "assert()"); 296 DCHECK(dst <= XMM15, "assert()"); 297 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 298 if (prefix1 >= 0) { 299 emitUint8(prefix1); 300 } 301 emitRegRegREX(dst, src, REX_W); 302 if (prefix2 >= 0) { 303 emitUint8(prefix2); 304 } 305 emitUint8(opcode); 306 emitRegisterOperand(dst & 7, src); 307} 308 309void Assembler::emitL(int dst, int src, int opcode, int prefix2, int prefix1) { 310 DCHECK(src <= XMM15, "assert()"); 311 DCHECK(dst <= XMM15, "assert()"); 312 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 313 if (prefix1 >= 0) { 314 emitUint8(prefix1); 315 } 316 emitRegRegREX(dst, src); 317 if (prefix2 >= 0) { 318 emitUint8(prefix2); 319 } 320 emitUint8(opcode); 321 emitRegisterOperand(dst & 7, src); 322} 323 324void Assembler::emitW(Register dst, Register src, int opcode, int prefix2, 325 int prefix1) { 326 DCHECK(src <= R15, "assert()"); 327 DCHECK(dst <= R15, "assert()"); 328 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 329 if (prefix1 >= 0) { 330 emitUint8(prefix1); 331 } 332 emitOperandSizeOverride(); 333 emitRegRegREX(dst, src); 334 if (prefix2 >= 0) { 335 emitUint8(prefix2); 336 } 337 emitUint8(opcode); 338 emitRegisterOperand(dst & 7, src); 339} 340 341void Assembler::cmpPS(XmmRegister dst, XmmRegister src, int condition) { 342 emitL(dst, src, 0xc2, 0x0f); 343 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 344 emitUint8(condition); 345} 346 347void Assembler::set1ps(XmmRegister dst, Register tmp, Immediate imm) { 348 // load 32-bit immediate value into tmp1. 349 movl(tmp, imm); 350 // Move value from tmp1 into dst. 351 movd(dst, tmp); 352 // Broadcast low lane into other three lanes. 353 shufps(dst, dst, Immediate(0x0)); 354} 355 356void Assembler::shufps(XmmRegister dst, XmmRegister src, Immediate mask) { 357 emitL(dst, src, 0xc6, 0x0f); 358 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 359 DCHECK(mask.isUint8(), "assert()"); 360 emitUint8(mask.value()); 361} 362 363void Assembler::shufpd(XmmRegister dst, XmmRegister src, Immediate mask) { 364 emitL(dst, src, 0xc6, 0x0f, 0x66); 365 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 366 DCHECK(mask.isUint8(), "assert()"); 367 emitUint8(mask.value()); 368} 369 370void Assembler::roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode) { 371 DCHECK(src <= XMM15, "assert()"); 372 DCHECK(dst <= XMM15, "assert()"); 373 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 374 emitUint8(0x66); 375 emitRegRegREX(dst, src); 376 emitUint8(0x0f); 377 emitUint8(0x3a); 378 emitUint8(0x0b); 379 emitRegisterOperand(dst & 7, src); 380 // Mask precision exeption. 381 emitUint8(static_cast<uint8_t>(mode) | 0x8); 382} 383 384void Assembler::fldl(Address src) { 385 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 386 emitUint8(0xdd); 387 emitOperand(0, src); 388} 389 390void Assembler::fstpl(Address dst) { 391 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 392 emitUint8(0xdd); 393 emitOperand(3, dst); 394} 395 396void Assembler::ffree(word value) { 397 DCHECK(value < 7, "assert()"); 398 emitSimple(0xdd, 0xc0 + value); 399} 400 401void Assembler::emitTestB(Operand operand, Immediate imm) { 402 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 403 if (operand.hasRegister(RAX)) { 404 emitUint8(0xa8); 405 } else { 406 emitOperandREX(0, operand, byteOperandREX(operand)); 407 emitUint8(0xf6); 408 emitOperand(0, operand); 409 } 410 DCHECK(imm.isInt8(), "immediate too large"); 411 emitUint8(imm.value()); 412} 413 414void Assembler::testb(Register dst, Register src) { 415 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 416 emitRegRegREX(dst, src, byteRegisterREX(dst) | byteRegisterREX(src)); 417 emitUint8(0x84); 418 emitRegisterOperand(dst & 7, src); 419} 420 421void Assembler::testb(Register reg, Immediate imm) { 422 emitTestB(Operand(reg), imm); 423} 424 425void Assembler::testb(Address address, Immediate imm) { 426 emitTestB(address, imm); 427} 428 429void Assembler::testb(Address address, Register reg) { 430 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 431 emitOperandREX(reg, address, byteRegisterREX(reg)); 432 emitUint8(0x84); 433 emitOperand(reg & 7, address); 434} 435 436void Assembler::emitTestQ(Operand operand, Immediate imm) { 437 // Try to emit a small instruction if the value of the immediate lets us. For 438 // Address operands, this relies on the fact that x86 is little-endian. 439 if (imm.isUint8()) { 440 emitTestB(operand, Immediate(static_cast<int8_t>(imm.value()))); 441 } else if (imm.isUint32()) { 442 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 443 if (operand.hasRegister(RAX)) { 444 emitUint8(0xa9); 445 } else { 446 emitOperandREX(0, operand, REX_NONE); 447 emitUint8(0xf7); 448 emitOperand(0, operand); 449 } 450 emitUInt32(imm.value()); 451 } else { 452 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 453 // Sign extended version of 32 bit test. 454 DCHECK(imm.isInt32(), "assert()"); 455 emitOperandREX(0, operand, REX_W); 456 if (operand.hasRegister(RAX)) { 457 emitUint8(0xa9); 458 } else { 459 emitUint8(0xf7); 460 emitOperand(0, operand); 461 } 462 emitInt32(imm.value()); 463 } 464} 465 466void Assembler::testq(Register reg, Immediate imm) { 467 emitTestQ(Operand(reg), imm); 468} 469 470void Assembler::testq(Address address, Immediate imm) { 471 emitTestQ(address, imm); 472} 473 474void Assembler::aluB(uint8_t modrm_opcode, Register dst, Immediate imm) { 475 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 476 Operand dst_operand(dst); 477 emitOperandREX(modrm_opcode, dst_operand, byteRegisterREX(dst)); 478 emitComplexB(modrm_opcode, dst_operand, imm); 479} 480 481void Assembler::aluL(uint8_t modrm_opcode, Register dst, Immediate imm) { 482 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 483 emitRegisterREX(dst, REX_NONE); 484 emitComplex(modrm_opcode, Operand(dst), imm); 485} 486 487void Assembler::aluB(uint8_t modrm_opcode, Address dst, Immediate imm) { 488 DCHECK(imm.isUint8() || imm.isInt8(), "assert()"); 489 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 490 emitOperandREX(modrm_opcode, dst, REX_NONE); 491 emitUint8(0x80); 492 emitOperand(modrm_opcode, dst); 493 emitUint8(imm.value() & 0xff); 494} 495 496void Assembler::aluW(uint8_t modrm_opcode, Address dst, Immediate imm) { 497 DCHECK(imm.isInt16() || imm.isUint16(), "assert()"); 498 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 499 emitOperandSizeOverride(); 500 emitOperandREX(modrm_opcode, dst, REX_NONE); 501 if (imm.isInt8()) { 502 emitSignExtendedInt8(modrm_opcode, dst, imm); 503 } else { 504 emitUint8(0x81); 505 emitOperand(modrm_opcode, dst); 506 emitUint8(imm.value() & 0xff); 507 emitUint8((imm.value() >> 8) & 0xff); 508 } 509} 510 511void Assembler::aluL(uint8_t modrm_opcode, Address dst, Immediate imm) { 512 DCHECK(imm.isInt32(), "assert()"); 513 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 514 emitOperandREX(modrm_opcode, dst, REX_NONE); 515 emitComplex(modrm_opcode, dst, imm); 516} 517 518void Assembler::aluQ(uint8_t modrm_opcode, uint8_t /*opcode*/, Register dst, 519 Immediate imm) { 520 Operand operand(dst); 521 if (modrm_opcode == 4 && imm.isUint32()) { 522 // We can use andl for andq. 523 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 524 emitRegisterREX(dst, REX_NONE); 525 // Would like to use emitComplex here, but it doesn't like uint32 526 // immediates. 527 if (imm.isInt8()) { 528 emitSignExtendedInt8(modrm_opcode, operand, imm); 529 } else { 530 if (dst == RAX) { 531 emitUint8(0x25); 532 } else { 533 emitUint8(0x81); 534 emitOperand(modrm_opcode, operand); 535 } 536 emitUInt32(imm.value()); 537 } 538 } else { 539 DCHECK(imm.isInt32(), "assert()"); 540 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 541 emitRegisterREX(dst, REX_W); 542 emitComplex(modrm_opcode, operand, imm); 543 } 544} 545 546void Assembler::aluQ(uint8_t modrm_opcode, uint8_t /*opcode*/, Address dst, 547 Immediate imm) { 548 DCHECK(imm.isInt32(), "assert()"); 549 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 550 emitOperandREX(modrm_opcode, dst, REX_W); 551 emitComplex(modrm_opcode, dst, imm); 552} 553 554void Assembler::cqo() { 555 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 556 emitRegisterREX(RAX, REX_W); 557 emitUint8(0x99); 558} 559 560void Assembler::emitUnaryQ(Register reg, int opcode, int modrm_code) { 561 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 562 emitRegisterREX(reg, REX_W); 563 emitUint8(opcode); 564 emitOperand(modrm_code, Operand(reg)); 565} 566 567void Assembler::emitUnaryL(Register reg, int opcode, int modrm_code) { 568 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 569 emitRegisterREX(reg, REX_NONE); 570 emitUint8(opcode); 571 emitOperand(modrm_code, Operand(reg)); 572} 573 574void Assembler::emitUnaryQ(Address address, int opcode, int modrm_code) { 575 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 576 Operand operand(address); 577 emitOperandREX(modrm_code, operand, REX_W); 578 emitUint8(opcode); 579 emitOperand(modrm_code, operand); 580} 581 582void Assembler::emitUnaryL(Address address, int opcode, int modrm_code) { 583 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 584 Operand operand(address); 585 emitOperandREX(modrm_code, operand, REX_NONE); 586 emitUint8(opcode); 587 emitOperand(modrm_code, operand); 588} 589 590void Assembler::imull(Register reg, Immediate imm) { 591 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 592 Operand operand(reg); 593 emitOperandREX(reg, operand, REX_NONE); 594 emitUint8(0x69); 595 emitOperand(reg & 7, Operand(reg)); 596 emitImmediate(imm); 597} 598 599void Assembler::shll(Register reg, Immediate imm) { 600 emitGenericShift(false, 4, reg, imm); 601} 602 603void Assembler::shll(Register operand, Register shifter) { 604 emitGenericShift(false, 4, operand, shifter); 605} 606 607void Assembler::shrl(Register reg, Immediate imm) { 608 emitGenericShift(false, 5, reg, imm); 609} 610 611void Assembler::shrl(Register operand, Register shifter) { 612 emitGenericShift(false, 5, operand, shifter); 613} 614 615void Assembler::sarl(Register reg, Immediate imm) { 616 emitGenericShift(false, 7, reg, imm); 617} 618 619void Assembler::sarl(Register operand, Register shifter) { 620 emitGenericShift(false, 7, operand, shifter); 621} 622 623void Assembler::shldl(Register dst, Register src, Immediate imm) { 624 emitL(src, dst, 0xa4, 0x0f); 625 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 626 DCHECK(imm.isInt8(), "assert()"); 627 emitUint8(imm.value() & 0xff); 628} 629 630void Assembler::shlq(Register reg, Immediate imm) { 631 emitGenericShift(true, 4, reg, imm); 632} 633 634void Assembler::shlq(Register operand, Register shifter) { 635 emitGenericShift(true, 4, operand, shifter); 636} 637 638void Assembler::shrq(Register reg, Immediate imm) { 639 emitGenericShift(true, 5, reg, imm); 640} 641 642void Assembler::shrq(Register operand, Register shifter) { 643 emitGenericShift(true, 5, operand, shifter); 644} 645 646void Assembler::sarq(Register reg, Immediate imm) { 647 emitGenericShift(true, 7, reg, imm); 648} 649 650void Assembler::sarq(Register operand, Register shifter) { 651 emitGenericShift(true, 7, operand, shifter); 652} 653 654void Assembler::shldq(Register dst, Register src, Immediate imm) { 655 emitQ(src, dst, 0xa4, 0x0f); 656 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 657 DCHECK(imm.isInt8(), "assert()"); 658 emitUint8(imm.value() & 0xff); 659} 660 661void Assembler::btq(Register base, int bit) { 662 DCHECK(bit >= 0 && bit < 64, "assert()"); 663 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 664 Operand operand(base); 665 emitOperandREX(4, operand, bit >= 32 ? REX_W : REX_NONE); 666 emitUint8(0x0f); 667 emitUint8(0xba); 668 emitOperand(4, operand); 669 emitUint8(bit); 670} 671 672void Assembler::enter(Immediate imm) { 673 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 674 emitUint8(0xc8); 675 DCHECK(imm.isUint16(), "assert()"); 676 emitUint8(imm.value() & 0xff); 677 emitUint8((imm.value() >> 8) & 0xff); 678 emitUint8(0x00); 679} 680 681void Assembler::nop(int size) { 682 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 683 // There are nops up to size 15, but for now just provide up to size 8. 684 DCHECK(0 < size && size <= kMaxNopSize, "assert()"); 685 switch (size) { 686 case 1: 687 emitUint8(0x90); 688 break; 689 case 2: 690 emitUint8(0x66); 691 emitUint8(0x90); 692 break; 693 case 3: 694 emitUint8(0x0f); 695 emitUint8(0x1f); 696 emitUint8(0x00); 697 break; 698 case 4: 699 emitUint8(0x0f); 700 emitUint8(0x1f); 701 emitUint8(0x40); 702 emitUint8(0x00); 703 break; 704 case 5: 705 emitUint8(0x0f); 706 emitUint8(0x1f); 707 emitUint8(0x44); 708 emitUint8(0x00); 709 emitUint8(0x00); 710 break; 711 case 6: 712 emitUint8(0x66); 713 emitUint8(0x0f); 714 emitUint8(0x1f); 715 emitUint8(0x44); 716 emitUint8(0x00); 717 emitUint8(0x00); 718 break; 719 case 7: 720 emitUint8(0x0f); 721 emitUint8(0x1f); 722 emitUint8(0x80); 723 emitUint8(0x00); 724 emitUint8(0x00); 725 emitUint8(0x00); 726 emitUint8(0x00); 727 break; 728 case 8: 729 emitUint8(0x0f); 730 emitUint8(0x1f); 731 emitUint8(0x84); 732 emitUint8(0x00); 733 emitUint8(0x00); 734 emitUint8(0x00); 735 emitUint8(0x00); 736 emitUint8(0x00); 737 break; 738 default: 739 UNIMPLEMENTED("default"); 740 } 741} 742 743void Assembler::nops(int size) { 744 DCHECK(size >= 0, "Can't emit negative nops"); 745 if (size == 0) return; 746 while (size > kMaxNopSize) { 747 nop(kMaxNopSize); 748 size -= kMaxNopSize; 749 } 750 nop(size); 751} 752 753void Assembler::ud2() { 754 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 755 emitUint8(0x0f); 756 emitUint8(0x0b); 757} 758 759void Assembler::jcc(Condition condition, Label* label, bool near) { 760 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 761 if (label->isBound()) { 762 static const int short_size = 2; 763 static const int long_size = 6; 764 word offset = label->position() - buffer_.size(); 765 DCHECK(offset <= 0, "assert()"); 766 if (Utils::fits<int8_t>(offset - short_size)) { 767 emitUint8(0x70 + condition); 768 emitUint8((offset - short_size) & 0xff); 769 } else { 770 emitUint8(0x0f); 771 emitUint8(0x80 + condition); 772 emitInt32(offset - long_size); 773 } 774 } else if (near) { 775 emitUint8(0x70 + condition); 776 emitNearLabelLink(label); 777 } else { 778 emitUint8(0x0f); 779 emitUint8(0x80 + condition); 780 emitLabelLink(label); 781 } 782} 783 784void Assembler::jmp(Label* label, bool near) { 785 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 786 if (label->isBound()) { 787 static const int short_size = 2; 788 static const int long_size = 5; 789 word offset = label->position() - buffer_.size(); 790 DCHECK(offset <= 0, "assert()"); 791 if (Utils::fits<int8_t>(offset - short_size)) { 792 emitUint8(0xeb); 793 emitUint8((offset - short_size) & 0xff); 794 } else { 795 emitUint8(0xe9); 796 emitInt32(offset - long_size); 797 } 798 } else if (near) { 799 emitUint8(0xeb); 800 emitNearLabelLink(label); 801 } else { 802 emitUint8(0xe9); 803 emitLabelLink(label); 804 } 805} 806 807void Assembler::bind(Label* label) { 808 word bound = buffer_.size(); 809 DCHECK(!label->isBound(), "assert()"); // Labels can only be bound once. 810 while (label->isLinked()) { 811 word position = label->linkPosition(); 812 word next = buffer_.load<int32_t>(position); 813 buffer_.store<int32_t>(position, bound - (position + 4)); 814 label->position_ = next; 815 } 816 while (label->hasNear()) { 817 word position = label->nearPosition(); 818 word offset = bound - (position + 1); 819 DCHECK(Utils::fits<int8_t>(offset), "assert()"); 820 buffer_.store<int8_t>(position, offset); 821 } 822 label->bindTo(bound); 823} 824 825void Assembler::comment(const char* format, ...) { 826 char comment_buffer[1024]; 827 va_list args; 828 ::va_start(args, format); 829 std::vsnprintf(comment_buffer, sizeof comment_buffer, format, args); 830 ::va_end(args); 831 comments_.add(new CodeComment(buffer_.getPosition(), comment_buffer)); 832} 833 834void Assembler::align(int alignment) { 835 DCHECK(Utils::isPowerOfTwo(alignment), "assert()"); 836 word pos = buffer_.getPosition(); 837 int mod = pos & (alignment - 1); 838 if (mod == 0) { 839 return; 840 } 841 word bytes_needed = alignment - mod; 842 while (bytes_needed > kMaxNopSize) { 843 nop(kMaxNopSize); 844 bytes_needed -= kMaxNopSize; 845 } 846 if (bytes_needed) { 847 nop(bytes_needed); 848 } 849 DCHECK((buffer_.getPosition() & (alignment - 1)) == 0, "assert()"); 850} 851 852void Assembler::emitOperand(int rm, Operand operand) { 853 DCHECK(rm >= 0 && rm < 8, "assert()"); 854 const word length = operand.length_; 855 DCHECK(length > 0, "assert()"); 856 // emit the ModRM byte updated with the given RM value. 857 DCHECK((operand.encoding_[0] & 0x38) == 0, "assert()"); 858 emitUint8(operand.encoding_[0] + (rm << 3)); 859 // emit the rest of the encoded operand. 860 for (word i = 1; i < length; i++) { 861 emitUint8(operand.encoding_[i]); 862 } 863} 864 865void Assembler::emitRegisterOperand(int rm, int reg) { 866 Operand operand; 867 operand.setModRM(3, static_cast<Register>(reg)); 868 emitOperand(rm, operand); 869} 870 871void Assembler::emitImmediate(Immediate imm) { 872 if (imm.isInt32()) { 873 emitInt32(static_cast<int32_t>(imm.value())); 874 } else { 875 emitInt64(imm.value()); 876 } 877} 878 879void Assembler::emitSignExtendedInt8(int rm, Operand operand, 880 Immediate immediate) { 881 emitUint8(0x83); 882 emitOperand(rm, operand); 883 emitUint8(immediate.value() & 0xff); 884} 885 886void Assembler::emitComplexB(int rm, Operand operand, Immediate imm) { 887 DCHECK(rm >= 0 && rm < 8, "assert()"); 888 DCHECK(imm.isUint8() || imm.isInt8(), "immediate too large"); 889 if (operand.hasRegister(RAX)) { 890 // Use short form if the destination is al. 891 emitUint8(0x04 + (rm << 3)); 892 } else { 893 emitUint8(0x80); 894 emitOperand(rm, operand); 895 } 896 emitUint8(imm.value()); 897} 898 899void Assembler::emitComplex(int rm, Operand operand, Immediate immediate) { 900 DCHECK(rm >= 0 && rm < 8, "assert()"); 901 DCHECK(immediate.isInt32(), "assert()"); 902 if (immediate.isInt8()) { 903 emitSignExtendedInt8(rm, operand, immediate); 904 } else if (operand.hasRegister(RAX)) { 905 // Use short form if the destination is rax. 906 emitUint8(0x05 + (rm << 3)); 907 emitImmediate(immediate); 908 } else { 909 emitUint8(0x81); 910 emitOperand(rm, operand); 911 emitImmediate(immediate); 912 } 913} 914 915void Assembler::emitLabel(Label* label, word instruction_size) { 916 if (label->isBound()) { 917 word offset = label->position() - buffer_.size(); 918 DCHECK(offset <= 0, "assert()"); 919 emitInt32(offset - instruction_size); 920 } else { 921 emitLabelLink(label); 922 } 923} 924 925void Assembler::emitLabelLink(Label* label) { 926 DCHECK(!label->isBound(), "assert()"); 927 word position = buffer_.size(); 928 emitInt32(label->position_); 929 label->linkTo(position); 930} 931 932void Assembler::emitNearLabelLink(Label* label) { 933 DCHECK(!label->isBound(), "assert()"); 934 word position = buffer_.size(); 935 emitUint8(0); 936 label->nearLinkTo(position); 937} 938 939void Assembler::emitGenericShift(bool wide, int rm, Register reg, 940 Immediate imm) { 941 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 942 DCHECK(imm.isInt8(), "assert()"); 943 if (wide) { 944 emitRegisterREX(reg, REX_W); 945 } else { 946 emitRegisterREX(reg, REX_NONE); 947 } 948 if (imm.value() == 1) { 949 emitUint8(0xd1); 950 emitOperand(rm, Operand(reg)); 951 } else { 952 emitUint8(0xc1); 953 emitOperand(rm, Operand(reg)); 954 emitUint8(imm.value() & 0xff); 955 } 956} 957 958void Assembler::emitGenericShift(bool wide, int rm, Register operand, 959 Register shifter) { 960 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 961 DCHECK(shifter == RCX, "assert()"); 962 emitRegisterREX(operand, wide ? REX_W : REX_NONE); 963 emitUint8(0xd3); 964 emitOperand(rm, Operand(operand)); 965} 966 967} // namespace x64 968} // namespace py