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