assembler_x86_64.h revision 3f6c7f61855172d3d9b7a9221baba76136088e7c
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_ 18#define ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_ 19 20#include <vector> 21#include "base/macros.h" 22#include "constants_x86_64.h" 23#include "globals.h" 24#include "managed_register_x86_64.h" 25#include "offsets.h" 26#include "utils/assembler.h" 27#include "utils.h" 28 29namespace art { 30namespace x86_64 { 31 32// Encodes an immediate value for operands. 33// 34// Note: Immediates can be 64b on x86-64 for certain instructions, but are often restricted 35// to 32b. 36// 37// Note: As we support cross-compilation, the value type must be int64_t. Please be aware of 38// conversion rules in expressions regarding negation, especially size_t on 32b. 39class Immediate : public ValueObject { 40 public: 41 explicit Immediate(int64_t value_in) : value_(value_in) {} 42 43 int64_t value() const { return value_; } 44 45 bool is_int8() const { return IsInt<8>(value_); } 46 bool is_uint8() const { return IsUint<8>(value_); } 47 bool is_int16() const { return IsInt<16>(value_); } 48 bool is_uint16() const { return IsUint<16>(value_); } 49 bool is_int32() const { return IsInt<32>(value_); } 50 51 private: 52 const int64_t value_; 53}; 54 55 56class Operand : public ValueObject { 57 public: 58 uint8_t mod() const { 59 return (encoding_at(0) >> 6) & 3; 60 } 61 62 Register rm() const { 63 return static_cast<Register>(encoding_at(0) & 7); 64 } 65 66 ScaleFactor scale() const { 67 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); 68 } 69 70 Register index() const { 71 return static_cast<Register>((encoding_at(1) >> 3) & 7); 72 } 73 74 Register base() const { 75 return static_cast<Register>(encoding_at(1) & 7); 76 } 77 78 uint8_t rex() const { 79 return rex_; 80 } 81 82 int8_t disp8() const { 83 CHECK_GE(length_, 2); 84 return static_cast<int8_t>(encoding_[length_ - 1]); 85 } 86 87 int32_t disp32() const { 88 CHECK_GE(length_, 5); 89 int32_t value; 90 memcpy(&value, &encoding_[length_ - 4], sizeof(value)); 91 return value; 92 } 93 94 bool IsRegister(CpuRegister reg) const { 95 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. 96 && ((encoding_[0] & 0x07) == reg.LowBits()) // Register codes match. 97 && (reg.NeedsRex() == ((rex_ & 1) != 0)); // REX.000B bits match. 98 } 99 100 protected: 101 // Operand can be sub classed (e.g: Address). 102 Operand() : rex_(0), length_(0) { } 103 104 void SetModRM(uint8_t mod_in, CpuRegister rm_in) { 105 CHECK_EQ(mod_in & ~3, 0); 106 if (rm_in.NeedsRex()) { 107 rex_ |= 0x41; // REX.000B 108 } 109 encoding_[0] = (mod_in << 6) | rm_in.LowBits(); 110 length_ = 1; 111 } 112 113 void SetSIB(ScaleFactor scale_in, CpuRegister index_in, CpuRegister base_in) { 114 CHECK_EQ(length_, 1); 115 CHECK_EQ(scale_in & ~3, 0); 116 if (base_in.NeedsRex()) { 117 rex_ |= 0x41; // REX.000B 118 } 119 if (index_in.NeedsRex()) { 120 rex_ |= 0x42; // REX.00X0 121 } 122 encoding_[1] = (scale_in << 6) | (static_cast<uint8_t>(index_in.LowBits()) << 3) | 123 static_cast<uint8_t>(base_in.LowBits()); 124 length_ = 2; 125 } 126 127 void SetDisp8(int8_t disp) { 128 CHECK(length_ == 1 || length_ == 2); 129 encoding_[length_++] = static_cast<uint8_t>(disp); 130 } 131 132 void SetDisp32(int32_t disp) { 133 CHECK(length_ == 1 || length_ == 2); 134 int disp_size = sizeof(disp); 135 memmove(&encoding_[length_], &disp, disp_size); 136 length_ += disp_size; 137 } 138 139 private: 140 uint8_t rex_; 141 uint8_t length_; 142 uint8_t encoding_[6]; 143 144 explicit Operand(CpuRegister reg) : rex_(0), length_(0) { SetModRM(3, reg); } 145 146 // Get the operand encoding byte at the given index. 147 uint8_t encoding_at(int index_in) const { 148 CHECK_GE(index_in, 0); 149 CHECK_LT(index_in, length_); 150 return encoding_[index_in]; 151 } 152 153 friend class X86_64Assembler; 154}; 155 156 157class Address : public Operand { 158 public: 159 Address(CpuRegister base_in, int32_t disp) { 160 Init(base_in, disp); 161 } 162 163 Address(CpuRegister base_in, Offset disp) { 164 Init(base_in, disp.Int32Value()); 165 } 166 167 Address(CpuRegister base_in, FrameOffset disp) { 168 CHECK_EQ(base_in.AsRegister(), RSP); 169 Init(CpuRegister(RSP), disp.Int32Value()); 170 } 171 172 Address(CpuRegister base_in, MemberOffset disp) { 173 Init(base_in, disp.Int32Value()); 174 } 175 176 void Init(CpuRegister base_in, int32_t disp) { 177 if (disp == 0 && base_in.LowBits() != RBP) { 178 SetModRM(0, base_in); 179 if (base_in.LowBits() == RSP) { 180 SetSIB(TIMES_1, CpuRegister(RSP), base_in); 181 } 182 } else if (disp >= -128 && disp <= 127) { 183 SetModRM(1, base_in); 184 if (base_in.LowBits() == RSP) { 185 SetSIB(TIMES_1, CpuRegister(RSP), base_in); 186 } 187 SetDisp8(disp); 188 } else { 189 SetModRM(2, base_in); 190 if (base_in.LowBits() == RSP) { 191 SetSIB(TIMES_1, CpuRegister(RSP), base_in); 192 } 193 SetDisp32(disp); 194 } 195 } 196 197 198 Address(CpuRegister index_in, ScaleFactor scale_in, int32_t disp) { 199 CHECK_NE(index_in.AsRegister(), RSP); // Illegal addressing mode. 200 SetModRM(0, CpuRegister(RSP)); 201 SetSIB(scale_in, index_in, CpuRegister(RBP)); 202 SetDisp32(disp); 203 } 204 205 Address(CpuRegister base_in, CpuRegister index_in, ScaleFactor scale_in, int32_t disp) { 206 CHECK_NE(index_in.AsRegister(), RSP); // Illegal addressing mode. 207 if (disp == 0 && base_in.LowBits() != RBP) { 208 SetModRM(0, CpuRegister(RSP)); 209 SetSIB(scale_in, index_in, base_in); 210 } else if (disp >= -128 && disp <= 127) { 211 SetModRM(1, CpuRegister(RSP)); 212 SetSIB(scale_in, index_in, base_in); 213 SetDisp8(disp); 214 } else { 215 SetModRM(2, CpuRegister(RSP)); 216 SetSIB(scale_in, index_in, base_in); 217 SetDisp32(disp); 218 } 219 } 220 221 // If no_rip is true then the Absolute address isn't RIP relative. 222 static Address Absolute(uintptr_t addr, bool no_rip = false) { 223 Address result; 224 if (no_rip) { 225 result.SetModRM(0, CpuRegister(RSP)); 226 result.SetSIB(TIMES_1, CpuRegister(RSP), CpuRegister(RBP)); 227 result.SetDisp32(addr); 228 } else { 229 result.SetModRM(0, CpuRegister(RBP)); 230 result.SetDisp32(addr); 231 } 232 return result; 233 } 234 235 // If no_rip is true then the Absolute address isn't RIP relative. 236 static Address Absolute(ThreadOffset<8> addr, bool no_rip = false) { 237 return Absolute(addr.Int32Value(), no_rip); 238 } 239 240 private: 241 Address() {} 242}; 243 244 245class X86_64Assembler FINAL : public Assembler { 246 public: 247 X86_64Assembler() : cfi_cfa_offset_(0), cfi_pc_(0) {} 248 virtual ~X86_64Assembler() {} 249 250 /* 251 * Emit Machine Instructions. 252 */ 253 void call(CpuRegister reg); 254 void call(const Address& address); 255 void call(Label* label); 256 257 void pushq(CpuRegister reg); 258 void pushq(const Address& address); 259 void pushq(const Immediate& imm); 260 261 void popq(CpuRegister reg); 262 void popq(const Address& address); 263 264 void movq(CpuRegister dst, const Immediate& src); 265 void movl(CpuRegister dst, const Immediate& src); 266 void movq(CpuRegister dst, CpuRegister src); 267 void movl(CpuRegister dst, CpuRegister src); 268 269 void movq(CpuRegister dst, const Address& src); 270 void movl(CpuRegister dst, const Address& src); 271 void movq(const Address& dst, CpuRegister src); 272 void movl(const Address& dst, CpuRegister src); 273 void movl(const Address& dst, const Immediate& imm); 274 275 void cmov(Condition c, CpuRegister dst, CpuRegister src); // This is the 64b version. 276 void cmov(Condition c, CpuRegister dst, CpuRegister src, bool is64bit); 277 278 void movzxb(CpuRegister dst, CpuRegister src); 279 void movzxb(CpuRegister dst, const Address& src); 280 void movsxb(CpuRegister dst, CpuRegister src); 281 void movsxb(CpuRegister dst, const Address& src); 282 void movb(CpuRegister dst, const Address& src); 283 void movb(const Address& dst, CpuRegister src); 284 void movb(const Address& dst, const Immediate& imm); 285 286 void movzxw(CpuRegister dst, CpuRegister src); 287 void movzxw(CpuRegister dst, const Address& src); 288 void movsxw(CpuRegister dst, CpuRegister src); 289 void movsxw(CpuRegister dst, const Address& src); 290 void movw(CpuRegister dst, const Address& src); 291 void movw(const Address& dst, CpuRegister src); 292 void movw(const Address& dst, const Immediate& imm); 293 294 void leaq(CpuRegister dst, const Address& src); 295 void leal(CpuRegister dst, const Address& src); 296 297 void movaps(XmmRegister dst, XmmRegister src); 298 299 void movss(XmmRegister dst, const Address& src); 300 void movss(const Address& dst, XmmRegister src); 301 void movss(XmmRegister dst, XmmRegister src); 302 303 void movsxd(CpuRegister dst, CpuRegister src); 304 void movsxd(CpuRegister dst, const Address& src); 305 306 void movd(XmmRegister dst, CpuRegister src); // Note: this is the r64 version, formally movq. 307 void movd(CpuRegister dst, XmmRegister src); // Note: this is the r64 version, formally movq. 308 void movd(XmmRegister dst, CpuRegister src, bool is64bit); 309 void movd(CpuRegister dst, XmmRegister src, bool is64bit); 310 311 void addss(XmmRegister dst, XmmRegister src); 312 void addss(XmmRegister dst, const Address& src); 313 void subss(XmmRegister dst, XmmRegister src); 314 void subss(XmmRegister dst, const Address& src); 315 void mulss(XmmRegister dst, XmmRegister src); 316 void mulss(XmmRegister dst, const Address& src); 317 void divss(XmmRegister dst, XmmRegister src); 318 void divss(XmmRegister dst, const Address& src); 319 320 void movsd(XmmRegister dst, const Address& src); 321 void movsd(const Address& dst, XmmRegister src); 322 void movsd(XmmRegister dst, XmmRegister src); 323 324 void addsd(XmmRegister dst, XmmRegister src); 325 void addsd(XmmRegister dst, const Address& src); 326 void subsd(XmmRegister dst, XmmRegister src); 327 void subsd(XmmRegister dst, const Address& src); 328 void mulsd(XmmRegister dst, XmmRegister src); 329 void mulsd(XmmRegister dst, const Address& src); 330 void divsd(XmmRegister dst, XmmRegister src); 331 void divsd(XmmRegister dst, const Address& src); 332 333 void cvtsi2ss(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version. 334 void cvtsi2ss(XmmRegister dst, CpuRegister src, bool is64bit); 335 void cvtsi2sd(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version. 336 void cvtsi2sd(XmmRegister dst, CpuRegister src, bool is64bit); 337 338 void cvtss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version. 339 void cvtss2sd(XmmRegister dst, XmmRegister src); 340 341 void cvtsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version. 342 void cvtsd2ss(XmmRegister dst, XmmRegister src); 343 344 void cvttss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version. 345 void cvttss2si(CpuRegister dst, XmmRegister src, bool is64bit); 346 void cvttsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version. 347 void cvttsd2si(CpuRegister dst, XmmRegister src, bool is64bit); 348 349 void cvtdq2pd(XmmRegister dst, XmmRegister src); 350 351 void comiss(XmmRegister a, XmmRegister b); 352 void comisd(XmmRegister a, XmmRegister b); 353 void ucomiss(XmmRegister a, XmmRegister b); 354 void ucomisd(XmmRegister a, XmmRegister b); 355 356 void sqrtsd(XmmRegister dst, XmmRegister src); 357 void sqrtss(XmmRegister dst, XmmRegister src); 358 359 void xorpd(XmmRegister dst, const Address& src); 360 void xorpd(XmmRegister dst, XmmRegister src); 361 void xorps(XmmRegister dst, const Address& src); 362 void xorps(XmmRegister dst, XmmRegister src); 363 364 void andpd(XmmRegister dst, const Address& src); 365 void andpd(XmmRegister dst, XmmRegister src); 366 void andps(XmmRegister dst, XmmRegister src); 367 368 void orpd(XmmRegister dst, XmmRegister src); 369 void orps(XmmRegister dst, XmmRegister src); 370 371 void flds(const Address& src); 372 void fstps(const Address& dst); 373 void fsts(const Address& dst); 374 375 void fldl(const Address& src); 376 void fstpl(const Address& dst); 377 void fstl(const Address& dst); 378 379 void fstsw(); 380 381 void fucompp(); 382 383 void fnstcw(const Address& dst); 384 void fldcw(const Address& src); 385 386 void fistpl(const Address& dst); 387 void fistps(const Address& dst); 388 void fildl(const Address& src); 389 390 void fincstp(); 391 void ffree(const Immediate& index); 392 393 void fsin(); 394 void fcos(); 395 void fptan(); 396 void fprem(); 397 398 void xchgl(CpuRegister dst, CpuRegister src); 399 void xchgq(CpuRegister dst, CpuRegister src); 400 void xchgl(CpuRegister reg, const Address& address); 401 402 void cmpw(const Address& address, const Immediate& imm); 403 404 void cmpl(CpuRegister reg, const Immediate& imm); 405 void cmpl(CpuRegister reg0, CpuRegister reg1); 406 void cmpl(CpuRegister reg, const Address& address); 407 void cmpl(const Address& address, CpuRegister reg); 408 void cmpl(const Address& address, const Immediate& imm); 409 410 void cmpq(CpuRegister reg0, CpuRegister reg1); 411 void cmpq(CpuRegister reg0, const Immediate& imm); 412 void cmpq(CpuRegister reg0, const Address& address); 413 void cmpq(const Address& address, const Immediate& imm); 414 415 void testl(CpuRegister reg1, CpuRegister reg2); 416 void testl(CpuRegister reg, const Address& address); 417 void testl(CpuRegister reg, const Immediate& imm); 418 419 void testq(CpuRegister reg1, CpuRegister reg2); 420 void testq(CpuRegister reg, const Address& address); 421 422 void andl(CpuRegister dst, const Immediate& imm); 423 void andl(CpuRegister dst, CpuRegister src); 424 void andl(CpuRegister reg, const Address& address); 425 void andq(CpuRegister dst, const Immediate& imm); 426 void andq(CpuRegister dst, CpuRegister src); 427 428 void orl(CpuRegister dst, const Immediate& imm); 429 void orl(CpuRegister dst, CpuRegister src); 430 void orl(CpuRegister reg, const Address& address); 431 void orq(CpuRegister dst, CpuRegister src); 432 void orq(CpuRegister dst, const Immediate& imm); 433 434 void xorl(CpuRegister dst, CpuRegister src); 435 void xorl(CpuRegister dst, const Immediate& imm); 436 void xorl(CpuRegister reg, const Address& address); 437 void xorq(CpuRegister dst, const Immediate& imm); 438 void xorq(CpuRegister dst, CpuRegister src); 439 440 void addl(CpuRegister dst, CpuRegister src); 441 void addl(CpuRegister reg, const Immediate& imm); 442 void addl(CpuRegister reg, const Address& address); 443 void addl(const Address& address, CpuRegister reg); 444 void addl(const Address& address, const Immediate& imm); 445 446 void addq(CpuRegister reg, const Immediate& imm); 447 void addq(CpuRegister dst, CpuRegister src); 448 void addq(CpuRegister dst, const Address& address); 449 450 void subl(CpuRegister dst, CpuRegister src); 451 void subl(CpuRegister reg, const Immediate& imm); 452 void subl(CpuRegister reg, const Address& address); 453 454 void subq(CpuRegister reg, const Immediate& imm); 455 void subq(CpuRegister dst, CpuRegister src); 456 void subq(CpuRegister dst, const Address& address); 457 458 void cdq(); 459 void cqo(); 460 461 void idivl(CpuRegister reg); 462 void idivq(CpuRegister reg); 463 464 void imull(CpuRegister dst, CpuRegister src); 465 void imull(CpuRegister reg, const Immediate& imm); 466 void imull(CpuRegister reg, const Address& address); 467 468 void imulq(CpuRegister dst, CpuRegister src); 469 void imulq(CpuRegister reg, const Immediate& imm); 470 void imulq(CpuRegister reg, const Address& address); 471 void imulq(CpuRegister dst, CpuRegister reg, const Immediate& imm); 472 473 void imull(CpuRegister reg); 474 void imull(const Address& address); 475 476 void mull(CpuRegister reg); 477 void mull(const Address& address); 478 479 void shll(CpuRegister reg, const Immediate& imm); 480 void shll(CpuRegister operand, CpuRegister shifter); 481 void shrl(CpuRegister reg, const Immediate& imm); 482 void shrl(CpuRegister operand, CpuRegister shifter); 483 void sarl(CpuRegister reg, const Immediate& imm); 484 void sarl(CpuRegister operand, CpuRegister shifter); 485 486 void shlq(CpuRegister reg, const Immediate& imm); 487 void shlq(CpuRegister operand, CpuRegister shifter); 488 void shrq(CpuRegister reg, const Immediate& imm); 489 void shrq(CpuRegister operand, CpuRegister shifter); 490 void sarq(CpuRegister reg, const Immediate& imm); 491 void sarq(CpuRegister operand, CpuRegister shifter); 492 493 void negl(CpuRegister reg); 494 void negq(CpuRegister reg); 495 496 void notl(CpuRegister reg); 497 void notq(CpuRegister reg); 498 499 void enter(const Immediate& imm); 500 void leave(); 501 502 void ret(); 503 void ret(const Immediate& imm); 504 505 void nop(); 506 void int3(); 507 void hlt(); 508 509 void j(Condition condition, Label* label); 510 511 void jmp(CpuRegister reg); 512 void jmp(const Address& address); 513 void jmp(Label* label); 514 515 X86_64Assembler* lock(); 516 void cmpxchgl(const Address& address, CpuRegister reg); 517 518 void mfence(); 519 520 X86_64Assembler* gs(); 521 522 void setcc(Condition condition, CpuRegister dst); 523 524 void bswapl(CpuRegister dst); 525 void bswapq(CpuRegister dst); 526 527 // 528 // Macros for High-level operations. 529 // 530 531 void AddImmediate(CpuRegister reg, const Immediate& imm); 532 533 void LoadDoubleConstant(XmmRegister dst, double value); 534 535 void LockCmpxchgl(const Address& address, CpuRegister reg) { 536 lock()->cmpxchgl(address, reg); 537 } 538 539 // 540 // Misc. functionality 541 // 542 int PreferredLoopAlignment() { return 16; } 543 void Align(int alignment, int offset); 544 void Bind(Label* label); 545 546 // 547 // Overridden common assembler high-level functionality 548 // 549 550 // Emit code that will create an activation on the stack 551 void BuildFrame(size_t frame_size, ManagedRegister method_reg, 552 const std::vector<ManagedRegister>& callee_save_regs, 553 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE; 554 555 // Emit code that will remove an activation from the stack 556 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs) 557 OVERRIDE; 558 559 void IncreaseFrameSize(size_t adjust) OVERRIDE; 560 void DecreaseFrameSize(size_t adjust) OVERRIDE; 561 562 // Store routines 563 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE; 564 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE; 565 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE; 566 567 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE; 568 569 void StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm, ManagedRegister scratch) 570 OVERRIDE; 571 572 void StoreStackOffsetToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, 573 ManagedRegister scratch) OVERRIDE; 574 575 void StoreStackPointerToThread64(ThreadOffset<8> thr_offs) OVERRIDE; 576 577 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off, 578 ManagedRegister scratch) OVERRIDE; 579 580 // Load routines 581 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE; 582 583 void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size) OVERRIDE; 584 585 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE; 586 587 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE; 588 589 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE; 590 591 void LoadRawPtrFromThread64(ManagedRegister dest, ThreadOffset<8> offs) OVERRIDE; 592 593 // Copying routines 594 void Move(ManagedRegister dest, ManagedRegister src, size_t size); 595 596 void CopyRawPtrFromThread64(FrameOffset fr_offs, ThreadOffset<8> thr_offs, 597 ManagedRegister scratch) OVERRIDE; 598 599 void CopyRawPtrToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, ManagedRegister scratch) 600 OVERRIDE; 601 602 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE; 603 604 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE; 605 606 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch, 607 size_t size) OVERRIDE; 608 609 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch, 610 size_t size) OVERRIDE; 611 612 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch, 613 size_t size) OVERRIDE; 614 615 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset, 616 ManagedRegister scratch, size_t size) OVERRIDE; 617 618 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, 619 ManagedRegister scratch, size_t size) OVERRIDE; 620 621 void MemoryBarrier(ManagedRegister) OVERRIDE; 622 623 // Sign extension 624 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE; 625 626 // Zero extension 627 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE; 628 629 // Exploit fast access in managed code to Thread::Current() 630 void GetCurrentThread(ManagedRegister tr) OVERRIDE; 631 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE; 632 633 // Set up out_reg to hold a Object** into the handle scope, or to be NULL if the 634 // value is null and null_allowed. in_reg holds a possibly stale reference 635 // that can be used to avoid loading the handle scope entry to see if the value is 636 // NULL. 637 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, ManagedRegister in_reg, 638 bool null_allowed) OVERRIDE; 639 640 // Set up out_off to hold a Object** into the handle scope, or to be NULL if the 641 // value is null and null_allowed. 642 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister scratch, 643 bool null_allowed) OVERRIDE; 644 645 // src holds a handle scope entry (Object**) load this into dst 646 virtual void LoadReferenceFromHandleScope(ManagedRegister dst, 647 ManagedRegister src); 648 649 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 650 // know that src may not be null. 651 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE; 652 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE; 653 654 // Call to address held at [base+offset] 655 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE; 656 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE; 657 void CallFromThread64(ThreadOffset<8> offset, ManagedRegister scratch) OVERRIDE; 658 659 // Generate code to check if Thread::Current()->exception_ is non-null 660 // and branch to a ExceptionSlowPath if it is. 661 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE; 662 663 void InitializeFrameDescriptionEntry() OVERRIDE; 664 void FinalizeFrameDescriptionEntry() OVERRIDE; 665 std::vector<uint8_t>* GetFrameDescriptionEntry() OVERRIDE { 666 return &cfi_info_; 667 } 668 669 private: 670 void EmitUint8(uint8_t value); 671 void EmitInt32(int32_t value); 672 void EmitInt64(int64_t value); 673 void EmitRegisterOperand(uint8_t rm, uint8_t reg); 674 void EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg); 675 void EmitFixup(AssemblerFixup* fixup); 676 void EmitOperandSizeOverride(); 677 678 void EmitOperand(uint8_t rm, const Operand& operand); 679 void EmitImmediate(const Immediate& imm); 680 void EmitComplex(uint8_t rm, const Operand& operand, const Immediate& immediate); 681 void EmitLabel(Label* label, int instruction_size); 682 void EmitLabelLink(Label* label); 683 void EmitNearLabelLink(Label* label); 684 685 void EmitGenericShift(bool wide, int rm, CpuRegister reg, const Immediate& imm); 686 void EmitGenericShift(bool wide, int rm, CpuRegister operand, CpuRegister shifter); 687 688 // If any input is not false, output the necessary rex prefix. 689 void EmitOptionalRex(bool force, bool w, bool r, bool x, bool b); 690 691 // Emit a rex prefix byte if necessary for reg. ie if reg is a register in the range R8 to R15. 692 void EmitOptionalRex32(CpuRegister reg); 693 void EmitOptionalRex32(CpuRegister dst, CpuRegister src); 694 void EmitOptionalRex32(XmmRegister dst, XmmRegister src); 695 void EmitOptionalRex32(CpuRegister dst, XmmRegister src); 696 void EmitOptionalRex32(XmmRegister dst, CpuRegister src); 697 void EmitOptionalRex32(const Operand& operand); 698 void EmitOptionalRex32(CpuRegister dst, const Operand& operand); 699 void EmitOptionalRex32(XmmRegister dst, const Operand& operand); 700 701 // Emit a REX.W prefix plus necessary register bit encodings. 702 void EmitRex64(); 703 void EmitRex64(CpuRegister reg); 704 void EmitRex64(const Operand& operand); 705 void EmitRex64(CpuRegister dst, CpuRegister src); 706 void EmitRex64(CpuRegister dst, const Operand& operand); 707 void EmitRex64(XmmRegister dst, CpuRegister src); 708 void EmitRex64(CpuRegister dst, XmmRegister src); 709 710 // Emit a REX prefix to normalize byte registers plus necessary register bit encodings. 711 void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, CpuRegister src); 712 void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, const Operand& operand); 713 714 std::vector<uint8_t> cfi_info_; 715 uint32_t cfi_cfa_offset_, cfi_pc_; 716 717 DISALLOW_COPY_AND_ASSIGN(X86_64Assembler); 718}; 719 720inline void X86_64Assembler::EmitUint8(uint8_t value) { 721 buffer_.Emit<uint8_t>(value); 722} 723 724inline void X86_64Assembler::EmitInt32(int32_t value) { 725 buffer_.Emit<int32_t>(value); 726} 727 728inline void X86_64Assembler::EmitInt64(int64_t value) { 729 // Write this 64-bit value as two 32-bit words for alignment reasons 730 // (this is essentially when running on ARM, which does not allow 731 // 64-bit unaligned accesses). We assume little-endianness here. 732 EmitInt32(Low32Bits(value)); 733 EmitInt32(High32Bits(value)); 734} 735 736inline void X86_64Assembler::EmitRegisterOperand(uint8_t rm, uint8_t reg) { 737 CHECK_GE(rm, 0); 738 CHECK_LT(rm, 8); 739 buffer_.Emit<uint8_t>((0xC0 | (reg & 7)) + (rm << 3)); 740} 741 742inline void X86_64Assembler::EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg) { 743 EmitRegisterOperand(rm, static_cast<uint8_t>(reg.AsFloatRegister())); 744} 745 746inline void X86_64Assembler::EmitFixup(AssemblerFixup* fixup) { 747 buffer_.EmitFixup(fixup); 748} 749 750inline void X86_64Assembler::EmitOperandSizeOverride() { 751 EmitUint8(0x66); 752} 753 754} // namespace x86_64 755} // namespace art 756 757#endif // ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_ 758