assembler_x86_64.h revision 3fd0e6a86430bf060c7eb391c1378394c4a2c574
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 movntl(const Address& dst, CpuRegister src); 330 void movntq(const Address& dst, CpuRegister src); 331 332 void movq(CpuRegister dst, const Address& src); 333 void movl(CpuRegister dst, const Address& src); 334 void movq(const Address& dst, CpuRegister src); 335 void movq(const Address& dst, const Immediate& src); 336 void movl(const Address& dst, CpuRegister src); 337 void movl(const Address& dst, const Immediate& imm); 338 339 void cmov(Condition c, CpuRegister dst, CpuRegister src); // This is the 64b version. 340 void cmov(Condition c, CpuRegister dst, CpuRegister src, bool is64bit); 341 342 void movzxb(CpuRegister dst, CpuRegister src); 343 void movzxb(CpuRegister dst, const Address& src); 344 void movsxb(CpuRegister dst, CpuRegister src); 345 void movsxb(CpuRegister dst, const Address& src); 346 void movb(CpuRegister dst, const Address& src); 347 void movb(const Address& dst, CpuRegister src); 348 void movb(const Address& dst, const Immediate& imm); 349 350 void movzxw(CpuRegister dst, CpuRegister src); 351 void movzxw(CpuRegister dst, const Address& src); 352 void movsxw(CpuRegister dst, CpuRegister src); 353 void movsxw(CpuRegister dst, const Address& src); 354 void movw(CpuRegister dst, const Address& src); 355 void movw(const Address& dst, CpuRegister src); 356 void movw(const Address& dst, const Immediate& imm); 357 358 void leaq(CpuRegister dst, const Address& src); 359 void leal(CpuRegister dst, const Address& src); 360 361 void movaps(XmmRegister dst, XmmRegister src); 362 363 void movss(XmmRegister dst, const Address& src); 364 void movss(const Address& dst, XmmRegister src); 365 void movss(XmmRegister dst, XmmRegister src); 366 367 void movsxd(CpuRegister dst, CpuRegister src); 368 void movsxd(CpuRegister dst, const Address& src); 369 370 void movd(XmmRegister dst, CpuRegister src); // Note: this is the r64 version, formally movq. 371 void movd(CpuRegister dst, XmmRegister src); // Note: this is the r64 version, formally movq. 372 void movd(XmmRegister dst, CpuRegister src, bool is64bit); 373 void movd(CpuRegister dst, XmmRegister src, bool is64bit); 374 375 void addss(XmmRegister dst, XmmRegister src); 376 void addss(XmmRegister dst, const Address& src); 377 void subss(XmmRegister dst, XmmRegister src); 378 void subss(XmmRegister dst, const Address& src); 379 void mulss(XmmRegister dst, XmmRegister src); 380 void mulss(XmmRegister dst, const Address& src); 381 void divss(XmmRegister dst, XmmRegister src); 382 void divss(XmmRegister dst, const Address& src); 383 384 void movsd(XmmRegister dst, const Address& src); 385 void movsd(const Address& dst, XmmRegister src); 386 void movsd(XmmRegister dst, XmmRegister src); 387 388 void addsd(XmmRegister dst, XmmRegister src); 389 void addsd(XmmRegister dst, const Address& src); 390 void subsd(XmmRegister dst, XmmRegister src); 391 void subsd(XmmRegister dst, const Address& src); 392 void mulsd(XmmRegister dst, XmmRegister src); 393 void mulsd(XmmRegister dst, const Address& src); 394 void divsd(XmmRegister dst, XmmRegister src); 395 void divsd(XmmRegister dst, const Address& src); 396 397 void cvtsi2ss(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version. 398 void cvtsi2ss(XmmRegister dst, CpuRegister src, bool is64bit); 399 void cvtsi2ss(XmmRegister dst, const Address& src, bool is64bit); 400 void cvtsi2sd(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version. 401 void cvtsi2sd(XmmRegister dst, CpuRegister src, bool is64bit); 402 void cvtsi2sd(XmmRegister dst, const Address& src, bool is64bit); 403 404 void cvtss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version. 405 void cvtss2sd(XmmRegister dst, XmmRegister src); 406 void cvtss2sd(XmmRegister dst, const Address& src); 407 408 void cvtsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version. 409 void cvtsd2ss(XmmRegister dst, XmmRegister src); 410 void cvtsd2ss(XmmRegister dst, const Address& src); 411 412 void cvttss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version. 413 void cvttss2si(CpuRegister dst, XmmRegister src, bool is64bit); 414 void cvttsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version. 415 void cvttsd2si(CpuRegister dst, XmmRegister src, bool is64bit); 416 417 void cvtdq2pd(XmmRegister dst, XmmRegister src); 418 419 void comiss(XmmRegister a, XmmRegister b); 420 void comiss(XmmRegister a, const Address& b); 421 void comisd(XmmRegister a, XmmRegister b); 422 void comisd(XmmRegister a, const Address& b); 423 void ucomiss(XmmRegister a, XmmRegister b); 424 void ucomiss(XmmRegister a, const Address& b); 425 void ucomisd(XmmRegister a, XmmRegister b); 426 void ucomisd(XmmRegister a, const Address& b); 427 428 void roundsd(XmmRegister dst, XmmRegister src, const Immediate& imm); 429 void roundss(XmmRegister dst, XmmRegister src, const Immediate& imm); 430 431 void sqrtsd(XmmRegister dst, XmmRegister src); 432 void sqrtss(XmmRegister dst, XmmRegister src); 433 434 void xorpd(XmmRegister dst, const Address& src); 435 void xorpd(XmmRegister dst, XmmRegister src); 436 void xorps(XmmRegister dst, const Address& src); 437 void xorps(XmmRegister dst, XmmRegister src); 438 439 void andpd(XmmRegister dst, const Address& src); 440 void andpd(XmmRegister dst, XmmRegister src); 441 void andps(XmmRegister dst, XmmRegister src); 442 443 void orpd(XmmRegister dst, XmmRegister src); 444 void orps(XmmRegister dst, XmmRegister src); 445 446 void flds(const Address& src); 447 void fstps(const Address& dst); 448 void fsts(const Address& dst); 449 450 void fldl(const Address& src); 451 void fstpl(const Address& dst); 452 void fstl(const Address& dst); 453 454 void fstsw(); 455 456 void fucompp(); 457 458 void fnstcw(const Address& dst); 459 void fldcw(const Address& src); 460 461 void fistpl(const Address& dst); 462 void fistps(const Address& dst); 463 void fildl(const Address& src); 464 void filds(const Address& src); 465 466 void fincstp(); 467 void ffree(const Immediate& index); 468 469 void fsin(); 470 void fcos(); 471 void fptan(); 472 void fprem(); 473 474 void xchgl(CpuRegister dst, CpuRegister src); 475 void xchgq(CpuRegister dst, CpuRegister src); 476 void xchgl(CpuRegister reg, const Address& address); 477 478 void cmpw(const Address& address, const Immediate& imm); 479 480 void cmpl(CpuRegister reg, const Immediate& imm); 481 void cmpl(CpuRegister reg0, CpuRegister reg1); 482 void cmpl(CpuRegister reg, const Address& address); 483 void cmpl(const Address& address, CpuRegister reg); 484 void cmpl(const Address& address, const Immediate& imm); 485 486 void cmpq(CpuRegister reg0, CpuRegister reg1); 487 void cmpq(CpuRegister reg0, const Immediate& imm); 488 void cmpq(CpuRegister reg0, const Address& address); 489 void cmpq(const Address& address, const Immediate& imm); 490 491 void testl(CpuRegister reg1, CpuRegister reg2); 492 void testl(CpuRegister reg, const Address& address); 493 void testl(CpuRegister reg, const Immediate& imm); 494 495 void testq(CpuRegister reg1, CpuRegister reg2); 496 void testq(CpuRegister reg, const Address& address); 497 498 void andl(CpuRegister dst, const Immediate& imm); 499 void andl(CpuRegister dst, CpuRegister src); 500 void andl(CpuRegister reg, const Address& address); 501 void andq(CpuRegister dst, const Immediate& imm); 502 void andq(CpuRegister dst, CpuRegister src); 503 void andq(CpuRegister reg, const Address& address); 504 505 void orl(CpuRegister dst, const Immediate& imm); 506 void orl(CpuRegister dst, CpuRegister src); 507 void orl(CpuRegister reg, const Address& address); 508 void orq(CpuRegister dst, CpuRegister src); 509 void orq(CpuRegister dst, const Immediate& imm); 510 void orq(CpuRegister reg, const Address& address); 511 512 void xorl(CpuRegister dst, CpuRegister src); 513 void xorl(CpuRegister dst, const Immediate& imm); 514 void xorl(CpuRegister reg, const Address& address); 515 void xorq(CpuRegister dst, const Immediate& imm); 516 void xorq(CpuRegister dst, CpuRegister src); 517 void xorq(CpuRegister reg, const Address& address); 518 519 void addl(CpuRegister dst, CpuRegister src); 520 void addl(CpuRegister reg, const Immediate& imm); 521 void addl(CpuRegister reg, const Address& address); 522 void addl(const Address& address, CpuRegister reg); 523 void addl(const Address& address, const Immediate& imm); 524 525 void addq(CpuRegister reg, const Immediate& imm); 526 void addq(CpuRegister dst, CpuRegister src); 527 void addq(CpuRegister dst, const Address& address); 528 529 void subl(CpuRegister dst, CpuRegister src); 530 void subl(CpuRegister reg, const Immediate& imm); 531 void subl(CpuRegister reg, const Address& address); 532 533 void subq(CpuRegister reg, const Immediate& imm); 534 void subq(CpuRegister dst, CpuRegister src); 535 void subq(CpuRegister dst, const Address& address); 536 537 void cdq(); 538 void cqo(); 539 540 void idivl(CpuRegister reg); 541 void idivq(CpuRegister reg); 542 543 void imull(CpuRegister dst, CpuRegister src); 544 void imull(CpuRegister reg, const Immediate& imm); 545 void imull(CpuRegister dst, CpuRegister src, const Immediate& imm); 546 void imull(CpuRegister reg, const Address& address); 547 548 void imulq(CpuRegister src); 549 void imulq(CpuRegister dst, CpuRegister src); 550 void imulq(CpuRegister reg, const Immediate& imm); 551 void imulq(CpuRegister reg, const Address& address); 552 void imulq(CpuRegister dst, CpuRegister reg, const Immediate& imm); 553 554 void imull(CpuRegister reg); 555 void imull(const Address& address); 556 557 void mull(CpuRegister reg); 558 void mull(const Address& address); 559 560 void shll(CpuRegister reg, const Immediate& imm); 561 void shll(CpuRegister operand, CpuRegister shifter); 562 void shrl(CpuRegister reg, const Immediate& imm); 563 void shrl(CpuRegister operand, CpuRegister shifter); 564 void sarl(CpuRegister reg, const Immediate& imm); 565 void sarl(CpuRegister operand, CpuRegister shifter); 566 567 void shlq(CpuRegister reg, const Immediate& imm); 568 void shlq(CpuRegister operand, CpuRegister shifter); 569 void shrq(CpuRegister reg, const Immediate& imm); 570 void shrq(CpuRegister operand, CpuRegister shifter); 571 void sarq(CpuRegister reg, const Immediate& imm); 572 void sarq(CpuRegister operand, CpuRegister shifter); 573 574 void negl(CpuRegister reg); 575 void negq(CpuRegister reg); 576 577 void notl(CpuRegister reg); 578 void notq(CpuRegister reg); 579 580 void enter(const Immediate& imm); 581 void leave(); 582 583 void ret(); 584 void ret(const Immediate& imm); 585 586 void nop(); 587 void int3(); 588 void hlt(); 589 590 void j(Condition condition, Label* label); 591 592 void jmp(CpuRegister reg); 593 void jmp(const Address& address); 594 void jmp(Label* label); 595 596 X86_64Assembler* lock(); 597 void cmpxchgl(const Address& address, CpuRegister reg); 598 void cmpxchgq(const Address& address, CpuRegister reg); 599 600 void mfence(); 601 602 X86_64Assembler* gs(); 603 604 void setcc(Condition condition, CpuRegister dst); 605 606 void bswapl(CpuRegister dst); 607 void bswapq(CpuRegister dst); 608 609 void repne_scasw(); 610 void repe_cmpsw(); 611 void repe_cmpsl(); 612 void repe_cmpsq(); 613 614 // 615 // Macros for High-level operations. 616 // 617 618 void AddImmediate(CpuRegister reg, const Immediate& imm); 619 620 void LoadDoubleConstant(XmmRegister dst, double value); 621 622 void LockCmpxchgl(const Address& address, CpuRegister reg) { 623 lock()->cmpxchgl(address, reg); 624 } 625 626 void LockCmpxchgq(const Address& address, CpuRegister reg) { 627 lock()->cmpxchgq(address, reg); 628 } 629 630 // 631 // Misc. functionality 632 // 633 int PreferredLoopAlignment() { return 16; } 634 void Align(int alignment, int offset); 635 void Bind(Label* label); 636 637 // 638 // Overridden common assembler high-level functionality 639 // 640 641 // Emit code that will create an activation on the stack 642 void BuildFrame(size_t frame_size, ManagedRegister method_reg, 643 const std::vector<ManagedRegister>& callee_save_regs, 644 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE; 645 646 // Emit code that will remove an activation from the stack 647 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs) 648 OVERRIDE; 649 650 void IncreaseFrameSize(size_t adjust) OVERRIDE; 651 void DecreaseFrameSize(size_t adjust) OVERRIDE; 652 653 // Store routines 654 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE; 655 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE; 656 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE; 657 658 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE; 659 660 void StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm, ManagedRegister scratch) 661 OVERRIDE; 662 663 void StoreStackOffsetToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, 664 ManagedRegister scratch) OVERRIDE; 665 666 void StoreStackPointerToThread64(ThreadOffset<8> thr_offs) OVERRIDE; 667 668 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off, 669 ManagedRegister scratch) OVERRIDE; 670 671 // Load routines 672 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE; 673 674 void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size) OVERRIDE; 675 676 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE; 677 678 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs, 679 bool unpoison_reference) OVERRIDE; 680 681 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE; 682 683 void LoadRawPtrFromThread64(ManagedRegister dest, ThreadOffset<8> offs) OVERRIDE; 684 685 // Copying routines 686 void Move(ManagedRegister dest, ManagedRegister src, size_t size); 687 688 void CopyRawPtrFromThread64(FrameOffset fr_offs, ThreadOffset<8> thr_offs, 689 ManagedRegister scratch) OVERRIDE; 690 691 void CopyRawPtrToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, ManagedRegister scratch) 692 OVERRIDE; 693 694 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE; 695 696 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE; 697 698 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch, 699 size_t size) OVERRIDE; 700 701 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch, 702 size_t size) OVERRIDE; 703 704 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch, 705 size_t size) OVERRIDE; 706 707 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset, 708 ManagedRegister scratch, size_t size) OVERRIDE; 709 710 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, 711 ManagedRegister scratch, size_t size) OVERRIDE; 712 713 void MemoryBarrier(ManagedRegister) OVERRIDE; 714 715 // Sign extension 716 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE; 717 718 // Zero extension 719 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE; 720 721 // Exploit fast access in managed code to Thread::Current() 722 void GetCurrentThread(ManagedRegister tr) OVERRIDE; 723 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE; 724 725 // Set up out_reg to hold a Object** into the handle scope, or to be null if the 726 // value is null and null_allowed. in_reg holds a possibly stale reference 727 // that can be used to avoid loading the handle scope entry to see if the value is 728 // null. 729 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, 730 ManagedRegister in_reg, bool null_allowed) OVERRIDE; 731 732 // Set up out_off to hold a Object** into the handle scope, or to be null if the 733 // value is null and null_allowed. 734 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, 735 ManagedRegister scratch, bool null_allowed) OVERRIDE; 736 737 // src holds a handle scope entry (Object**) load this into dst 738 virtual void LoadReferenceFromHandleScope(ManagedRegister dst, 739 ManagedRegister src); 740 741 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 742 // know that src may not be null. 743 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE; 744 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE; 745 746 // Call to address held at [base+offset] 747 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE; 748 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE; 749 void CallFromThread64(ThreadOffset<8> offset, ManagedRegister scratch) OVERRIDE; 750 751 // Generate code to check if Thread::Current()->exception_ is non-null 752 // and branch to a ExceptionSlowPath if it is. 753 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE; 754 755 // Add a double to the constant area, returning the offset into 756 // the constant area where the literal resides. 757 int AddDouble(double v) { return constant_area_.AddDouble(v); } 758 759 // Add a float to the constant area, returning the offset into 760 // the constant area where the literal resides. 761 int AddFloat(float v) { return constant_area_.AddFloat(v); } 762 763 // Add an int32_t to the constant area, returning the offset into 764 // the constant area where the literal resides. 765 int AddInt32(int32_t v) { return constant_area_.AddInt32(v); } 766 767 // Add an int64_t to the constant area, returning the offset into 768 // the constant area where the literal resides. 769 int AddInt64(int64_t v) { return constant_area_.AddInt64(v); } 770 771 // Add the contents of the constant area to the assembler buffer. 772 void AddConstantArea(); 773 774 // Is the constant area empty? Return true if there are no literals in the constant area. 775 bool IsConstantAreaEmpty() const { return constant_area_.GetSize() == 0; } 776 777 // 778 // Heap poisoning. 779 // 780 781 // Poison a heap reference contained in `reg`. 782 void PoisonHeapReference(CpuRegister reg) { negl(reg); } 783 // Unpoison a heap reference contained in `reg`. 784 void UnpoisonHeapReference(CpuRegister reg) { negl(reg); } 785 // Unpoison a heap reference contained in `reg` if heap poisoning is enabled. 786 void MaybeUnpoisonHeapReference(CpuRegister reg) { 787 if (kPoisonHeapReferences) { 788 UnpoisonHeapReference(reg); 789 } 790 } 791 792 private: 793 void EmitUint8(uint8_t value); 794 void EmitInt32(int32_t value); 795 void EmitInt64(int64_t value); 796 void EmitRegisterOperand(uint8_t rm, uint8_t reg); 797 void EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg); 798 void EmitFixup(AssemblerFixup* fixup); 799 void EmitOperandSizeOverride(); 800 801 void EmitOperand(uint8_t rm, const Operand& operand); 802 void EmitImmediate(const Immediate& imm); 803 void EmitComplex(uint8_t rm, const Operand& operand, const Immediate& immediate); 804 void EmitLabel(Label* label, int instruction_size); 805 void EmitLabelLink(Label* label); 806 void EmitNearLabelLink(Label* label); 807 808 void EmitGenericShift(bool wide, int rm, CpuRegister reg, const Immediate& imm); 809 void EmitGenericShift(bool wide, int rm, CpuRegister operand, CpuRegister shifter); 810 811 // If any input is not false, output the necessary rex prefix. 812 void EmitOptionalRex(bool force, bool w, bool r, bool x, bool b); 813 814 // Emit a rex prefix byte if necessary for reg. ie if reg is a register in the range R8 to R15. 815 void EmitOptionalRex32(CpuRegister reg); 816 void EmitOptionalRex32(CpuRegister dst, CpuRegister src); 817 void EmitOptionalRex32(XmmRegister dst, XmmRegister src); 818 void EmitOptionalRex32(CpuRegister dst, XmmRegister src); 819 void EmitOptionalRex32(XmmRegister dst, CpuRegister src); 820 void EmitOptionalRex32(const Operand& operand); 821 void EmitOptionalRex32(CpuRegister dst, const Operand& operand); 822 void EmitOptionalRex32(XmmRegister dst, const Operand& operand); 823 824 // Emit a REX.W prefix plus necessary register bit encodings. 825 void EmitRex64(); 826 void EmitRex64(CpuRegister reg); 827 void EmitRex64(const Operand& operand); 828 void EmitRex64(CpuRegister dst, CpuRegister src); 829 void EmitRex64(CpuRegister dst, const Operand& operand); 830 void EmitRex64(XmmRegister dst, const Operand& operand); 831 void EmitRex64(XmmRegister dst, CpuRegister src); 832 void EmitRex64(CpuRegister dst, XmmRegister src); 833 834 // Emit a REX prefix to normalize byte registers plus necessary register bit encodings. 835 void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, CpuRegister src); 836 void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, const Operand& operand); 837 838 ConstantArea constant_area_; 839 840 DISALLOW_COPY_AND_ASSIGN(X86_64Assembler); 841}; 842 843inline void X86_64Assembler::EmitUint8(uint8_t value) { 844 buffer_.Emit<uint8_t>(value); 845} 846 847inline void X86_64Assembler::EmitInt32(int32_t value) { 848 buffer_.Emit<int32_t>(value); 849} 850 851inline void X86_64Assembler::EmitInt64(int64_t value) { 852 // Write this 64-bit value as two 32-bit words for alignment reasons 853 // (this is essentially when running on ARM, which does not allow 854 // 64-bit unaligned accesses). We assume little-endianness here. 855 EmitInt32(Low32Bits(value)); 856 EmitInt32(High32Bits(value)); 857} 858 859inline void X86_64Assembler::EmitRegisterOperand(uint8_t rm, uint8_t reg) { 860 CHECK_GE(rm, 0); 861 CHECK_LT(rm, 8); 862 buffer_.Emit<uint8_t>((0xC0 | (reg & 7)) + (rm << 3)); 863} 864 865inline void X86_64Assembler::EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg) { 866 EmitRegisterOperand(rm, static_cast<uint8_t>(reg.AsFloatRegister())); 867} 868 869inline void X86_64Assembler::EmitFixup(AssemblerFixup* fixup) { 870 buffer_.EmitFixup(fixup); 871} 872 873inline void X86_64Assembler::EmitOperandSizeOverride() { 874 EmitUint8(0x66); 875} 876 877} // namespace x86_64 878} // namespace art 879 880#endif // ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_ 881