1 /* 2 * Copyright (C) 2011 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_ASSEMBLER_X86_H_ 18 #define ART_COMPILER_UTILS_X86_ASSEMBLER_X86_H_ 19 20 #include <vector> 21 #include "base/macros.h" 22 #include "constants_x86.h" 23 #include "globals.h" 24 #include "managed_register_x86.h" 25 #include "offsets.h" 26 #include "utils/assembler.h" 27 #include "utils.h" 28 29 namespace art { 30 namespace x86 { 31 32 class Immediate { 33 public: 34 explicit Immediate(int32_t value) : value_(value) {} 35 36 int32_t value() const { return value_; } 37 38 bool is_int8() const { return IsInt(8, value_); } 39 bool is_uint8() const { return IsUint(8, value_); } 40 bool is_uint16() const { return IsUint(16, value_); } 41 42 private: 43 const int32_t value_; 44 45 DISALLOW_COPY_AND_ASSIGN(Immediate); 46 }; 47 48 49 class Operand { 50 public: 51 uint8_t mod() const { 52 return (encoding_at(0) >> 6) & 3; 53 } 54 55 Register rm() const { 56 return static_cast<Register>(encoding_at(0) & 7); 57 } 58 59 ScaleFactor scale() const { 60 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); 61 } 62 63 Register index() const { 64 return static_cast<Register>((encoding_at(1) >> 3) & 7); 65 } 66 67 Register base() const { 68 return static_cast<Register>(encoding_at(1) & 7); 69 } 70 71 int8_t disp8() const { 72 CHECK_GE(length_, 2); 73 return static_cast<int8_t>(encoding_[length_ - 1]); 74 } 75 76 int32_t disp32() const { 77 CHECK_GE(length_, 5); 78 int32_t value; 79 memcpy(&value, &encoding_[length_ - 4], sizeof(value)); 80 return value; 81 } 82 83 bool IsRegister(Register reg) const { 84 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. 85 && ((encoding_[0] & 0x07) == reg); // Register codes match. 86 } 87 88 protected: 89 // Operand can be sub classed (e.g: Address). 90 Operand() : length_(0) { } 91 92 void SetModRM(int mod, Register rm) { 93 CHECK_EQ(mod & ~3, 0); 94 encoding_[0] = (mod << 6) | rm; 95 length_ = 1; 96 } 97 98 void SetSIB(ScaleFactor scale, Register index, Register base) { 99 CHECK_EQ(length_, 1); 100 CHECK_EQ(scale & ~3, 0); 101 encoding_[1] = (scale << 6) | (index << 3) | base; 102 length_ = 2; 103 } 104 105 void SetDisp8(int8_t disp) { 106 CHECK(length_ == 1 || length_ == 2); 107 encoding_[length_++] = static_cast<uint8_t>(disp); 108 } 109 110 void SetDisp32(int32_t disp) { 111 CHECK(length_ == 1 || length_ == 2); 112 int disp_size = sizeof(disp); 113 memmove(&encoding_[length_], &disp, disp_size); 114 length_ += disp_size; 115 } 116 117 private: 118 byte length_; 119 byte encoding_[6]; 120 byte padding_; 121 122 explicit Operand(Register reg) { SetModRM(3, reg); } 123 124 // Get the operand encoding byte at the given index. 125 uint8_t encoding_at(int index) const { 126 CHECK_GE(index, 0); 127 CHECK_LT(index, length_); 128 return encoding_[index]; 129 } 130 131 friend class X86Assembler; 132 133 DISALLOW_COPY_AND_ASSIGN(Operand); 134 }; 135 136 137 class Address : public Operand { 138 public: 139 Address(Register base, int32_t disp) { 140 Init(base, disp); 141 } 142 143 Address(Register base, Offset disp) { 144 Init(base, disp.Int32Value()); 145 } 146 147 Address(Register base, FrameOffset disp) { 148 CHECK_EQ(base, ESP); 149 Init(ESP, disp.Int32Value()); 150 } 151 152 Address(Register base, MemberOffset disp) { 153 Init(base, disp.Int32Value()); 154 } 155 156 void Init(Register base, int32_t disp) { 157 if (disp == 0 && base != EBP) { 158 SetModRM(0, base); 159 if (base == ESP) SetSIB(TIMES_1, ESP, base); 160 } else if (disp >= -128 && disp <= 127) { 161 SetModRM(1, base); 162 if (base == ESP) SetSIB(TIMES_1, ESP, base); 163 SetDisp8(disp); 164 } else { 165 SetModRM(2, base); 166 if (base == ESP) SetSIB(TIMES_1, ESP, base); 167 SetDisp32(disp); 168 } 169 } 170 171 172 Address(Register index, ScaleFactor scale, int32_t disp) { 173 CHECK_NE(index, ESP); // Illegal addressing mode. 174 SetModRM(0, ESP); 175 SetSIB(scale, index, EBP); 176 SetDisp32(disp); 177 } 178 179 Address(Register base, Register index, ScaleFactor scale, int32_t disp) { 180 CHECK_NE(index, ESP); // Illegal addressing mode. 181 if (disp == 0 && base != EBP) { 182 SetModRM(0, ESP); 183 SetSIB(scale, index, base); 184 } else if (disp >= -128 && disp <= 127) { 185 SetModRM(1, ESP); 186 SetSIB(scale, index, base); 187 SetDisp8(disp); 188 } else { 189 SetModRM(2, ESP); 190 SetSIB(scale, index, base); 191 SetDisp32(disp); 192 } 193 } 194 195 static Address Absolute(uword addr) { 196 Address result; 197 result.SetModRM(0, EBP); 198 result.SetDisp32(addr); 199 return result; 200 } 201 202 static Address Absolute(ThreadOffset addr) { 203 return Absolute(addr.Int32Value()); 204 } 205 206 private: 207 Address() {} 208 209 DISALLOW_COPY_AND_ASSIGN(Address); 210 }; 211 212 213 class X86Assembler : public Assembler { 214 public: 215 X86Assembler() {} 216 virtual ~X86Assembler() {} 217 218 /* 219 * Emit Machine Instructions. 220 */ 221 void call(Register reg); 222 void call(const Address& address); 223 void call(Label* label); 224 225 void pushl(Register reg); 226 void pushl(const Address& address); 227 void pushl(const Immediate& imm); 228 229 void popl(Register reg); 230 void popl(const Address& address); 231 232 void movl(Register dst, const Immediate& src); 233 void movl(Register dst, Register src); 234 235 void movl(Register dst, const Address& src); 236 void movl(const Address& dst, Register src); 237 void movl(const Address& dst, const Immediate& imm); 238 void movl(const Address& dst, Label* lbl); 239 240 void movzxb(Register dst, ByteRegister src); 241 void movzxb(Register dst, const Address& src); 242 void movsxb(Register dst, ByteRegister src); 243 void movsxb(Register dst, const Address& src); 244 void movb(Register dst, const Address& src); 245 void movb(const Address& dst, ByteRegister src); 246 void movb(const Address& dst, const Immediate& imm); 247 248 void movzxw(Register dst, Register src); 249 void movzxw(Register dst, const Address& src); 250 void movsxw(Register dst, Register src); 251 void movsxw(Register dst, const Address& src); 252 void movw(Register dst, const Address& src); 253 void movw(const Address& dst, Register src); 254 255 void leal(Register dst, const Address& src); 256 257 void cmovl(Condition condition, Register dst, Register src); 258 259 void setb(Condition condition, Register dst); 260 261 void movss(XmmRegister dst, const Address& src); 262 void movss(const Address& dst, XmmRegister src); 263 void movss(XmmRegister dst, XmmRegister src); 264 265 void movd(XmmRegister dst, Register src); 266 void movd(Register dst, XmmRegister src); 267 268 void addss(XmmRegister dst, XmmRegister src); 269 void addss(XmmRegister dst, const Address& src); 270 void subss(XmmRegister dst, XmmRegister src); 271 void subss(XmmRegister dst, const Address& src); 272 void mulss(XmmRegister dst, XmmRegister src); 273 void mulss(XmmRegister dst, const Address& src); 274 void divss(XmmRegister dst, XmmRegister src); 275 void divss(XmmRegister dst, const Address& src); 276 277 void movsd(XmmRegister dst, const Address& src); 278 void movsd(const Address& dst, XmmRegister src); 279 void movsd(XmmRegister dst, XmmRegister src); 280 281 void addsd(XmmRegister dst, XmmRegister src); 282 void addsd(XmmRegister dst, const Address& src); 283 void subsd(XmmRegister dst, XmmRegister src); 284 void subsd(XmmRegister dst, const Address& src); 285 void mulsd(XmmRegister dst, XmmRegister src); 286 void mulsd(XmmRegister dst, const Address& src); 287 void divsd(XmmRegister dst, XmmRegister src); 288 void divsd(XmmRegister dst, const Address& src); 289 290 void cvtsi2ss(XmmRegister dst, Register src); 291 void cvtsi2sd(XmmRegister dst, Register src); 292 293 void cvtss2si(Register dst, XmmRegister src); 294 void cvtss2sd(XmmRegister dst, XmmRegister src); 295 296 void cvtsd2si(Register dst, XmmRegister src); 297 void cvtsd2ss(XmmRegister dst, XmmRegister src); 298 299 void cvttss2si(Register dst, XmmRegister src); 300 void cvttsd2si(Register dst, XmmRegister src); 301 302 void cvtdq2pd(XmmRegister dst, XmmRegister src); 303 304 void comiss(XmmRegister a, XmmRegister b); 305 void comisd(XmmRegister a, XmmRegister b); 306 307 void sqrtsd(XmmRegister dst, XmmRegister src); 308 void sqrtss(XmmRegister dst, XmmRegister src); 309 310 void xorpd(XmmRegister dst, const Address& src); 311 void xorpd(XmmRegister dst, XmmRegister src); 312 void xorps(XmmRegister dst, const Address& src); 313 void xorps(XmmRegister dst, XmmRegister src); 314 315 void andpd(XmmRegister dst, const Address& src); 316 317 void flds(const Address& src); 318 void fstps(const Address& dst); 319 320 void fldl(const Address& src); 321 void fstpl(const Address& dst); 322 323 void fnstcw(const Address& dst); 324 void fldcw(const Address& src); 325 326 void fistpl(const Address& dst); 327 void fistps(const Address& dst); 328 void fildl(const Address& src); 329 330 void fincstp(); 331 void ffree(const Immediate& index); 332 333 void fsin(); 334 void fcos(); 335 void fptan(); 336 337 void xchgl(Register dst, Register src); 338 void xchgl(Register reg, const Address& address); 339 340 void cmpl(Register reg, const Immediate& imm); 341 void cmpl(Register reg0, Register reg1); 342 void cmpl(Register reg, const Address& address); 343 344 void cmpl(const Address& address, Register reg); 345 void cmpl(const Address& address, const Immediate& imm); 346 347 void testl(Register reg1, Register reg2); 348 void testl(Register reg, const Immediate& imm); 349 350 void andl(Register dst, const Immediate& imm); 351 void andl(Register dst, Register src); 352 353 void orl(Register dst, const Immediate& imm); 354 void orl(Register dst, Register src); 355 356 void xorl(Register dst, Register src); 357 358 void addl(Register dst, Register src); 359 void addl(Register reg, const Immediate& imm); 360 void addl(Register reg, const Address& address); 361 362 void addl(const Address& address, Register reg); 363 void addl(const Address& address, const Immediate& imm); 364 365 void adcl(Register dst, Register src); 366 void adcl(Register reg, const Immediate& imm); 367 void adcl(Register dst, const Address& address); 368 369 void subl(Register dst, Register src); 370 void subl(Register reg, const Immediate& imm); 371 void subl(Register reg, const Address& address); 372 373 void cdq(); 374 375 void idivl(Register reg); 376 377 void imull(Register dst, Register src); 378 void imull(Register reg, const Immediate& imm); 379 void imull(Register reg, const Address& address); 380 381 void imull(Register reg); 382 void imull(const Address& address); 383 384 void mull(Register reg); 385 void mull(const Address& address); 386 387 void sbbl(Register dst, Register src); 388 void sbbl(Register reg, const Immediate& imm); 389 void sbbl(Register reg, const Address& address); 390 391 void incl(Register reg); 392 void incl(const Address& address); 393 394 void decl(Register reg); 395 void decl(const Address& address); 396 397 void shll(Register reg, const Immediate& imm); 398 void shll(Register operand, Register shifter); 399 void shrl(Register reg, const Immediate& imm); 400 void shrl(Register operand, Register shifter); 401 void sarl(Register reg, const Immediate& imm); 402 void sarl(Register operand, Register shifter); 403 void shld(Register dst, Register src); 404 405 void negl(Register reg); 406 void notl(Register reg); 407 408 void enter(const Immediate& imm); 409 void leave(); 410 411 void ret(); 412 void ret(const Immediate& imm); 413 414 void nop(); 415 void int3(); 416 void hlt(); 417 418 void j(Condition condition, Label* label); 419 420 void jmp(Register reg); 421 void jmp(const Address& address); 422 void jmp(Label* label); 423 424 X86Assembler* lock(); 425 void cmpxchgl(const Address& address, Register reg); 426 427 void mfence(); 428 429 X86Assembler* fs(); 430 431 // 432 // Macros for High-level operations. 433 // 434 435 void AddImmediate(Register reg, const Immediate& imm); 436 437 void LoadDoubleConstant(XmmRegister dst, double value); 438 439 void DoubleNegate(XmmRegister d); 440 void FloatNegate(XmmRegister f); 441 442 void DoubleAbs(XmmRegister reg); 443 444 void LockCmpxchgl(const Address& address, Register reg) { 445 lock()->cmpxchgl(address, reg); 446 } 447 448 // 449 // Misc. functionality 450 // 451 int PreferredLoopAlignment() { return 16; } 452 void Align(int alignment, int offset); 453 void Bind(Label* label); 454 455 // Debugging and bringup support. 456 void Stop(const char* message); 457 458 // 459 // Overridden common assembler high-level functionality 460 // 461 462 // Emit code that will create an activation on the stack 463 virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg, 464 const std::vector<ManagedRegister>& callee_save_regs, 465 const std::vector<ManagedRegister>& entry_spills); 466 467 // Emit code that will remove an activation from the stack 468 virtual void RemoveFrame(size_t frame_size, 469 const std::vector<ManagedRegister>& callee_save_regs); 470 471 virtual void IncreaseFrameSize(size_t adjust); 472 virtual void DecreaseFrameSize(size_t adjust); 473 474 // Store routines 475 virtual void Store(FrameOffset offs, ManagedRegister src, size_t size); 476 virtual void StoreRef(FrameOffset dest, ManagedRegister src); 477 virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src); 478 479 virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, 480 ManagedRegister scratch); 481 482 virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm, 483 ManagedRegister scratch); 484 485 virtual void StoreStackOffsetToThread(ThreadOffset thr_offs, 486 FrameOffset fr_offs, 487 ManagedRegister scratch); 488 489 virtual void StoreStackPointerToThread(ThreadOffset thr_offs); 490 491 void StoreLabelToThread(ThreadOffset thr_offs, Label* lbl); 492 493 virtual void StoreSpanning(FrameOffset dest, ManagedRegister src, 494 FrameOffset in_off, ManagedRegister scratch); 495 496 // Load routines 497 virtual void Load(ManagedRegister dest, FrameOffset src, size_t size); 498 499 virtual void Load(ManagedRegister dest, ThreadOffset src, size_t size); 500 501 virtual void LoadRef(ManagedRegister dest, FrameOffset src); 502 503 virtual void LoadRef(ManagedRegister dest, ManagedRegister base, 504 MemberOffset offs); 505 506 virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base, 507 Offset offs); 508 509 virtual void LoadRawPtrFromThread(ManagedRegister dest, 510 ThreadOffset offs); 511 512 // Copying routines 513 virtual void Move(ManagedRegister dest, ManagedRegister src, size_t size); 514 515 virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs, 516 ManagedRegister scratch); 517 518 virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs, 519 ManagedRegister scratch); 520 521 virtual void CopyRef(FrameOffset dest, FrameOffset src, 522 ManagedRegister scratch); 523 524 virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size); 525 526 virtual void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, 527 ManagedRegister scratch, size_t size); 528 529 virtual void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, 530 ManagedRegister scratch, size_t size); 531 532 virtual void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, 533 ManagedRegister scratch, size_t size); 534 535 virtual void Copy(ManagedRegister dest, Offset dest_offset, 536 ManagedRegister src, Offset src_offset, 537 ManagedRegister scratch, size_t size); 538 539 virtual void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, 540 ManagedRegister scratch, size_t size); 541 542 virtual void MemoryBarrier(ManagedRegister); 543 544 // Sign extension 545 virtual void SignExtend(ManagedRegister mreg, size_t size); 546 547 // Zero extension 548 virtual void ZeroExtend(ManagedRegister mreg, size_t size); 549 550 // Exploit fast access in managed code to Thread::Current() 551 virtual void GetCurrentThread(ManagedRegister tr); 552 virtual void GetCurrentThread(FrameOffset dest_offset, 553 ManagedRegister scratch); 554 555 // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the 556 // value is null and null_allowed. in_reg holds a possibly stale reference 557 // that can be used to avoid loading the SIRT entry to see if the value is 558 // NULL. 559 virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset, 560 ManagedRegister in_reg, bool null_allowed); 561 562 // Set up out_off to hold a Object** into the SIRT, or to be NULL if the 563 // value is null and null_allowed. 564 virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset, 565 ManagedRegister scratch, bool null_allowed); 566 567 // src holds a SIRT entry (Object**) load this into dst 568 virtual void LoadReferenceFromSirt(ManagedRegister dst, 569 ManagedRegister src); 570 571 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 572 // know that src may not be null. 573 virtual void VerifyObject(ManagedRegister src, bool could_be_null); 574 virtual void VerifyObject(FrameOffset src, bool could_be_null); 575 576 // Call to address held at [base+offset] 577 virtual void Call(ManagedRegister base, Offset offset, 578 ManagedRegister scratch); 579 virtual void Call(FrameOffset base, Offset offset, 580 ManagedRegister scratch); 581 virtual void Call(ThreadOffset offset, ManagedRegister scratch); 582 583 // Generate code to check if Thread::Current()->exception_ is non-null 584 // and branch to a ExceptionSlowPath if it is. 585 virtual void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust); 586 587 private: 588 inline void EmitUint8(uint8_t value); 589 inline void EmitInt32(int32_t value); 590 inline void EmitRegisterOperand(int rm, int reg); 591 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg); 592 inline void EmitFixup(AssemblerFixup* fixup); 593 inline void EmitOperandSizeOverride(); 594 595 void EmitOperand(int rm, const Operand& operand); 596 void EmitImmediate(const Immediate& imm); 597 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate); 598 void EmitLabel(Label* label, int instruction_size); 599 void EmitLabelLink(Label* label); 600 void EmitNearLabelLink(Label* label); 601 602 void EmitGenericShift(int rm, Register reg, const Immediate& imm); 603 void EmitGenericShift(int rm, Register operand, Register shifter); 604 605 DISALLOW_COPY_AND_ASSIGN(X86Assembler); 606 }; 607 608 inline void X86Assembler::EmitUint8(uint8_t value) { 609 buffer_.Emit<uint8_t>(value); 610 } 611 612 inline void X86Assembler::EmitInt32(int32_t value) { 613 buffer_.Emit<int32_t>(value); 614 } 615 616 inline void X86Assembler::EmitRegisterOperand(int rm, int reg) { 617 CHECK_GE(rm, 0); 618 CHECK_LT(rm, 8); 619 buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg); 620 } 621 622 inline void X86Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) { 623 EmitRegisterOperand(rm, static_cast<Register>(reg)); 624 } 625 626 inline void X86Assembler::EmitFixup(AssemblerFixup* fixup) { 627 buffer_.EmitFixup(fixup); 628 } 629 630 inline void X86Assembler::EmitOperandSizeOverride() { 631 EmitUint8(0x66); 632 } 633 634 // Slowpath entered when Thread::Current()->_exception is non-null 635 class X86ExceptionSlowPath : public SlowPath { 636 public: 637 explicit X86ExceptionSlowPath(size_t stack_adjust) : stack_adjust_(stack_adjust) {} 638 virtual void Emit(Assembler *sp_asm); 639 private: 640 const size_t stack_adjust_; 641 }; 642 643 } // namespace x86 644 } // namespace art 645 646 #endif // ART_COMPILER_UTILS_X86_ASSEMBLER_X86_H_ 647