assembler_x86.h revision f12feb8e0e857f2832545b3f28d31bad5a9d3903
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 29namespace art { 30namespace x86 { 31 32class 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 49class 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 121 explicit Operand(Register reg) { SetModRM(3, reg); } 122 123 // Get the operand encoding byte at the given index. 124 uint8_t encoding_at(int index) const { 125 CHECK_GE(index, 0); 126 CHECK_LT(index, length_); 127 return encoding_[index]; 128 } 129 130 friend class X86Assembler; 131 132 DISALLOW_COPY_AND_ASSIGN(Operand); 133}; 134 135 136class Address : public Operand { 137 public: 138 Address(Register base, int32_t disp) { 139 Init(base, disp); 140 } 141 142 Address(Register base, Offset disp) { 143 Init(base, disp.Int32Value()); 144 } 145 146 Address(Register base, FrameOffset disp) { 147 CHECK_EQ(base, ESP); 148 Init(ESP, disp.Int32Value()); 149 } 150 151 Address(Register base, MemberOffset disp) { 152 Init(base, disp.Int32Value()); 153 } 154 155 void Init(Register base, int32_t disp) { 156 if (disp == 0 && base != EBP) { 157 SetModRM(0, base); 158 if (base == ESP) SetSIB(TIMES_1, ESP, base); 159 } else if (disp >= -128 && disp <= 127) { 160 SetModRM(1, base); 161 if (base == ESP) SetSIB(TIMES_1, ESP, base); 162 SetDisp8(disp); 163 } else { 164 SetModRM(2, base); 165 if (base == ESP) SetSIB(TIMES_1, ESP, base); 166 SetDisp32(disp); 167 } 168 } 169 170 171 Address(Register index, ScaleFactor scale, int32_t disp) { 172 CHECK_NE(index, ESP); // Illegal addressing mode. 173 SetModRM(0, ESP); 174 SetSIB(scale, index, EBP); 175 SetDisp32(disp); 176 } 177 178 Address(Register base, Register index, ScaleFactor scale, int32_t disp) { 179 CHECK_NE(index, ESP); // Illegal addressing mode. 180 if (disp == 0 && base != EBP) { 181 SetModRM(0, ESP); 182 SetSIB(scale, index, base); 183 } else if (disp >= -128 && disp <= 127) { 184 SetModRM(1, ESP); 185 SetSIB(scale, index, base); 186 SetDisp8(disp); 187 } else { 188 SetModRM(2, ESP); 189 SetSIB(scale, index, base); 190 SetDisp32(disp); 191 } 192 } 193 194 static Address Absolute(uword addr) { 195 Address result; 196 result.SetModRM(0, EBP); 197 result.SetDisp32(addr); 198 return result; 199 } 200 201 static Address Absolute(ThreadOffset<4> addr) { 202 return Absolute(addr.Int32Value()); 203 } 204 205 private: 206 Address() {} 207 208 DISALLOW_COPY_AND_ASSIGN(Address); 209}; 210 211 212class X86Assembler FINAL : public Assembler { 213 public: 214 explicit X86Assembler() {} 215 virtual ~X86Assembler() {} 216 217 /* 218 * Emit Machine Instructions. 219 */ 220 void call(Register reg); 221 void call(const Address& address); 222 void call(Label* label); 223 void call(const ExternalLabel& 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 void testl(Register reg1, const Address& address); 350 351 void andl(Register dst, const Immediate& imm); 352 void andl(Register dst, Register src); 353 354 void orl(Register dst, const Immediate& imm); 355 void orl(Register dst, Register src); 356 357 void xorl(Register dst, Register src); 358 void xorl(Register dst, const Immediate& imm); 359 360 void addl(Register dst, Register src); 361 void addl(Register reg, const Immediate& imm); 362 void addl(Register reg, const Address& address); 363 364 void addl(const Address& address, Register reg); 365 void addl(const Address& address, const Immediate& imm); 366 367 void adcl(Register dst, Register src); 368 void adcl(Register reg, const Immediate& imm); 369 void adcl(Register dst, const Address& address); 370 371 void subl(Register dst, Register src); 372 void subl(Register reg, const Immediate& imm); 373 void subl(Register reg, const Address& address); 374 375 void cdq(); 376 377 void idivl(Register reg); 378 379 void imull(Register dst, Register src); 380 void imull(Register reg, const Immediate& imm); 381 void imull(Register reg, const Address& address); 382 383 void imull(Register reg); 384 void imull(const Address& address); 385 386 void mull(Register reg); 387 void mull(const Address& address); 388 389 void sbbl(Register dst, Register src); 390 void sbbl(Register reg, const Immediate& imm); 391 void sbbl(Register reg, const Address& address); 392 393 void incl(Register reg); 394 void incl(const Address& address); 395 396 void decl(Register reg); 397 void decl(const Address& address); 398 399 void shll(Register reg, const Immediate& imm); 400 void shll(Register operand, Register shifter); 401 void shrl(Register reg, const Immediate& imm); 402 void shrl(Register operand, Register shifter); 403 void sarl(Register reg, const Immediate& imm); 404 void sarl(Register operand, Register shifter); 405 void shld(Register dst, Register src); 406 407 void negl(Register reg); 408 void notl(Register reg); 409 410 void enter(const Immediate& imm); 411 void leave(); 412 413 void ret(); 414 void ret(const Immediate& imm); 415 416 void nop(); 417 void int3(); 418 void hlt(); 419 420 void j(Condition condition, Label* label); 421 422 void jmp(Register reg); 423 void jmp(const Address& address); 424 void jmp(Label* label); 425 426 X86Assembler* lock(); 427 void cmpxchgl(const Address& address, Register reg); 428 429 void mfence(); 430 431 X86Assembler* fs(); 432 X86Assembler* gs(); 433 434 // 435 // Macros for High-level operations. 436 // 437 438 void AddImmediate(Register reg, const Immediate& imm); 439 440 void LoadDoubleConstant(XmmRegister dst, double value); 441 442 void DoubleNegate(XmmRegister d); 443 void FloatNegate(XmmRegister f); 444 445 void DoubleAbs(XmmRegister reg); 446 447 void LockCmpxchgl(const Address& address, Register reg) { 448 lock()->cmpxchgl(address, reg); 449 } 450 451 // 452 // Misc. functionality 453 // 454 int PreferredLoopAlignment() { return 16; } 455 void Align(int alignment, int offset); 456 void Bind(Label* label); 457 458 // 459 // Overridden common assembler high-level functionality 460 // 461 462 // Emit code that will create an activation on the stack 463 void BuildFrame(size_t frame_size, ManagedRegister method_reg, 464 const std::vector<ManagedRegister>& callee_save_regs, 465 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE; 466 467 // Emit code that will remove an activation from the stack 468 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs) 469 OVERRIDE; 470 471 void IncreaseFrameSize(size_t adjust) OVERRIDE; 472 void DecreaseFrameSize(size_t adjust) OVERRIDE; 473 474 // Store routines 475 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE; 476 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE; 477 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE; 478 479 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE; 480 481 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch) 482 OVERRIDE; 483 484 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, 485 ManagedRegister scratch) OVERRIDE; 486 487 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE; 488 489 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off, 490 ManagedRegister scratch) OVERRIDE; 491 492 // Load routines 493 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE; 494 495 void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE; 496 497 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE; 498 499 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE; 500 501 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE; 502 503 void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE; 504 505 // Copying routines 506 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE; 507 508 void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs, 509 ManagedRegister scratch) OVERRIDE; 510 511 void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch) 512 OVERRIDE; 513 514 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE; 515 516 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE; 517 518 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch, 519 size_t size) OVERRIDE; 520 521 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch, 522 size_t size) OVERRIDE; 523 524 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch, 525 size_t size) OVERRIDE; 526 527 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset, 528 ManagedRegister scratch, size_t size) OVERRIDE; 529 530 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, 531 ManagedRegister scratch, size_t size) OVERRIDE; 532 533 void MemoryBarrier(ManagedRegister) OVERRIDE; 534 535 // Sign extension 536 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE; 537 538 // Zero extension 539 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE; 540 541 // Exploit fast access in managed code to Thread::Current() 542 void GetCurrentThread(ManagedRegister tr) OVERRIDE; 543 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE; 544 545 // Set up out_reg to hold a Object** into the handle scope, or to be NULL if the 546 // value is null and null_allowed. in_reg holds a possibly stale reference 547 // that can be used to avoid loading the handle scope entry to see if the value is 548 // NULL. 549 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, ManagedRegister in_reg, 550 bool null_allowed) OVERRIDE; 551 552 // Set up out_off to hold a Object** into the handle scope, or to be NULL if the 553 // value is null and null_allowed. 554 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister scratch, 555 bool null_allowed) OVERRIDE; 556 557 // src holds a handle scope entry (Object**) load this into dst 558 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE; 559 560 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 561 // know that src may not be null. 562 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE; 563 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE; 564 565 // Call to address held at [base+offset] 566 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE; 567 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE; 568 void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE; 569 570 // Generate code to check if Thread::Current()->exception_ is non-null 571 // and branch to a ExceptionSlowPath if it is. 572 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE; 573 574 private: 575 inline void EmitUint8(uint8_t value); 576 inline void EmitInt32(int32_t value); 577 inline void EmitRegisterOperand(int rm, int reg); 578 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg); 579 inline void EmitFixup(AssemblerFixup* fixup); 580 inline void EmitOperandSizeOverride(); 581 582 void EmitOperand(int rm, const Operand& operand); 583 void EmitImmediate(const Immediate& imm); 584 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate); 585 void EmitLabel(Label* label, int instruction_size); 586 void EmitLabelLink(Label* label); 587 void EmitNearLabelLink(Label* label); 588 589 void EmitGenericShift(int rm, Register reg, const Immediate& imm); 590 void EmitGenericShift(int rm, Register operand, Register shifter); 591 592 DISALLOW_COPY_AND_ASSIGN(X86Assembler); 593}; 594 595inline void X86Assembler::EmitUint8(uint8_t value) { 596 buffer_.Emit<uint8_t>(value); 597} 598 599inline void X86Assembler::EmitInt32(int32_t value) { 600 buffer_.Emit<int32_t>(value); 601} 602 603inline void X86Assembler::EmitRegisterOperand(int rm, int reg) { 604 CHECK_GE(rm, 0); 605 CHECK_LT(rm, 8); 606 buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg); 607} 608 609inline void X86Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) { 610 EmitRegisterOperand(rm, static_cast<Register>(reg)); 611} 612 613inline void X86Assembler::EmitFixup(AssemblerFixup* fixup) { 614 buffer_.EmitFixup(fixup); 615} 616 617inline void X86Assembler::EmitOperandSizeOverride() { 618 EmitUint8(0x66); 619} 620 621// Slowpath entered when Thread::Current()->_exception is non-null 622class X86ExceptionSlowPath FINAL : public SlowPath { 623 public: 624 explicit X86ExceptionSlowPath(size_t stack_adjust) : stack_adjust_(stack_adjust) {} 625 virtual void Emit(Assembler *sp_asm) OVERRIDE; 626 private: 627 const size_t stack_adjust_; 628}; 629 630} // namespace x86 631} // namespace art 632 633#endif // ART_COMPILER_UTILS_X86_ASSEMBLER_X86_H_ 634