assembler_x86.h revision 6b6b5f0e67ce03f38223a525612955663bc1799b
1// Copyright 2011 Google Inc. All Rights Reserved. 2 3#ifndef ART_SRC_ASSEMBLER_X86_H_ 4#define ART_SRC_ASSEMBLER_X86_H_ 5 6#include <stdint.h> 7#include <string.h> 8#include "src/constants_x86.h" 9#include "src/macros.h" 10#include "src/utils.h" 11 12namespace art { 13 14class Immediate { 15 public: 16 explicit Immediate(int32_t value) : value_(value) {} 17 18 int32_t value() const { return value_; } 19 20 bool is_int8() const { return IsInt(8, value_); } 21 bool is_uint8() const { return IsUint(8, value_); } 22 bool is_uint16() const { return IsUint(16, value_); } 23 24 private: 25 const int32_t value_; 26 27 DISALLOW_COPY_AND_ASSIGN(Immediate); 28}; 29 30 31class Operand { 32 public: 33 uint8_t mod() const { 34 return (encoding_at(0) >> 6) & 3; 35 } 36 37 Register rm() const { 38 return static_cast<Register>(encoding_at(0) & 7); 39 } 40 41 ScaleFactor scale() const { 42 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); 43 } 44 45 Register index() const { 46 return static_cast<Register>((encoding_at(1) >> 3) & 7); 47 } 48 49 Register base() const { 50 return static_cast<Register>(encoding_at(1) & 7); 51 } 52 53 int8_t disp8() const { 54 CHECK_GE(length_, 2); 55 return static_cast<int8_t>(encoding_[length_ - 1]); 56 } 57 58 int32_t disp32() const { 59 CHECK_GE(length_, 5); 60 int32_t value; 61 memcpy(&value, &encoding_[length_ - 4], sizeof(value)); 62 return value; 63 } 64 65 bool IsRegister(Register reg) const { 66 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. 67 && ((encoding_[0] & 0x07) == reg); // Register codes match. 68 } 69 70 protected: 71 // Operand can be sub classed (e.g: Address). 72 Operand() : length_(0) { } 73 74 void SetModRM(int mod, Register rm) { 75 CHECK_EQ(mod & ~3, 0); 76 encoding_[0] = (mod << 6) | rm; 77 length_ = 1; 78 } 79 80 void SetSIB(ScaleFactor scale, Register index, Register base) { 81 CHECK_EQ(length_, 1); 82 CHECK_EQ(scale & ~3, 0); 83 encoding_[1] = (scale << 6) | (index << 3) | base; 84 length_ = 2; 85 } 86 87 void SetDisp8(int8_t disp) { 88 CHECK(length_ == 1 || length_ == 2); 89 encoding_[length_++] = static_cast<uint8_t>(disp); 90 } 91 92 void SetDisp32(int32_t disp) { 93 CHECK(length_ == 1 || length_ == 2); 94 int disp_size = sizeof(disp); 95 memmove(&encoding_[length_], &disp, disp_size); 96 length_ += disp_size; 97 } 98 99 private: 100 byte length_; 101 byte encoding_[6]; 102 byte padding_; 103 104 explicit Operand(Register reg) { SetModRM(3, reg); } 105 106 // Get the operand encoding byte at the given index. 107 uint8_t encoding_at(int index) const { 108 CHECK_GE(index, 0); 109 CHECK_LT(index, length_); 110 return encoding_[index]; 111 } 112 113 friend class Assembler; 114 115 DISALLOW_COPY_AND_ASSIGN(Operand); 116}; 117 118 119class Address : public Operand { 120 public: 121 Address(Register base, int32_t disp) { 122 if (disp == 0 && base != EBP) { 123 SetModRM(0, base); 124 if (base == ESP) SetSIB(TIMES_1, ESP, base); 125 } else if (disp >= -128 && disp <= 127) { 126 SetModRM(1, base); 127 if (base == ESP) SetSIB(TIMES_1, ESP, base); 128 SetDisp8(disp); 129 } else { 130 SetModRM(2, base); 131 if (base == ESP) SetSIB(TIMES_1, ESP, base); 132 SetDisp32(disp); 133 } 134 } 135 136 Address(Register index, ScaleFactor scale, int32_t disp) { 137 CHECK_NE(index, ESP); // Illegal addressing mode. 138 SetModRM(0, ESP); 139 SetSIB(scale, index, EBP); 140 SetDisp32(disp); 141 } 142 143 Address(Register base, Register index, ScaleFactor scale, int32_t disp) { 144 CHECK_NE(index, ESP); // Illegal addressing mode. 145 if (disp == 0 && base != EBP) { 146 SetModRM(0, ESP); 147 SetSIB(scale, index, base); 148 } else if (disp >= -128 && disp <= 127) { 149 SetModRM(1, ESP); 150 SetSIB(scale, index, base); 151 SetDisp8(disp); 152 } else { 153 SetModRM(2, ESP); 154 SetSIB(scale, index, base); 155 SetDisp32(disp); 156 } 157 } 158 159 static Address Absolute(const uword addr) { 160 Address result; 161 result.SetModRM(0, EBP); 162 result.SetDisp32(addr); 163 return result; 164 } 165 166 private: 167 Address() {} 168 169 DISALLOW_COPY_AND_ASSIGN(Address); 170}; 171 172 173class Assembler { 174 public: 175 Assembler() : buffer_() {} 176 ~Assembler() {} 177 178 /* 179 * Emit Machine Instructions. 180 */ 181 void call(Register reg); 182 void call(const Address& address); 183 void call(Label* label); 184 185 void pushl(Register reg); 186 void pushl(const Address& address); 187 void pushl(const Immediate& imm); 188 189 void popl(Register reg); 190 void popl(const Address& address); 191 192 void movl(Register dst, const Immediate& src); 193 void movl(Register dst, Register src); 194 195 void movl(Register dst, const Address& src); 196 void movl(const Address& dst, Register src); 197 void movl(const Address& dst, const Immediate& imm); 198 199 void movzxb(Register dst, ByteRegister src); 200 void movzxb(Register dst, const Address& src); 201 void movsxb(Register dst, ByteRegister src); 202 void movsxb(Register dst, const Address& src); 203 void movb(Register dst, const Address& src); 204 void movb(const Address& dst, ByteRegister src); 205 void movb(const Address& dst, const Immediate& imm); 206 207 void movzxw(Register dst, Register src); 208 void movzxw(Register dst, const Address& src); 209 void movsxw(Register dst, Register src); 210 void movsxw(Register dst, const Address& src); 211 void movw(Register dst, const Address& src); 212 void movw(const Address& dst, Register src); 213 214 void leal(Register dst, const Address& src); 215 216 void cmovs(Register dst, Register src); 217 void cmovns(Register dst, Register src); 218 219 void movss(XmmRegister dst, const Address& src); 220 void movss(const Address& dst, XmmRegister src); 221 void movss(XmmRegister dst, XmmRegister src); 222 223 void movd(XmmRegister dst, Register src); 224 void movd(Register dst, XmmRegister src); 225 226 void addss(XmmRegister dst, XmmRegister src); 227 void addss(XmmRegister dst, const Address& src); 228 void subss(XmmRegister dst, XmmRegister src); 229 void subss(XmmRegister dst, const Address& src); 230 void mulss(XmmRegister dst, XmmRegister src); 231 void mulss(XmmRegister dst, const Address& src); 232 void divss(XmmRegister dst, XmmRegister src); 233 void divss(XmmRegister dst, const Address& src); 234 235 void movsd(XmmRegister dst, const Address& src); 236 void movsd(const Address& dst, XmmRegister src); 237 void movsd(XmmRegister dst, XmmRegister src); 238 239 void addsd(XmmRegister dst, XmmRegister src); 240 void addsd(XmmRegister dst, const Address& src); 241 void subsd(XmmRegister dst, XmmRegister src); 242 void subsd(XmmRegister dst, const Address& src); 243 void mulsd(XmmRegister dst, XmmRegister src); 244 void mulsd(XmmRegister dst, const Address& src); 245 void divsd(XmmRegister dst, XmmRegister src); 246 void divsd(XmmRegister dst, const Address& src); 247 248 void cvtsi2ss(XmmRegister dst, Register src); 249 void cvtsi2sd(XmmRegister dst, Register src); 250 251 void cvtss2si(Register dst, XmmRegister src); 252 void cvtss2sd(XmmRegister dst, XmmRegister src); 253 254 void cvtsd2si(Register dst, XmmRegister src); 255 void cvtsd2ss(XmmRegister dst, XmmRegister src); 256 257 void cvttss2si(Register dst, XmmRegister src); 258 void cvttsd2si(Register dst, XmmRegister src); 259 260 void cvtdq2pd(XmmRegister dst, XmmRegister src); 261 262 void comiss(XmmRegister a, XmmRegister b); 263 void comisd(XmmRegister a, XmmRegister b); 264 265 void sqrtsd(XmmRegister dst, XmmRegister src); 266 void sqrtss(XmmRegister dst, XmmRegister src); 267 268 void xorpd(XmmRegister dst, const Address& src); 269 void xorpd(XmmRegister dst, XmmRegister src); 270 void xorps(XmmRegister dst, const Address& src); 271 void xorps(XmmRegister dst, XmmRegister src); 272 273 void andpd(XmmRegister dst, const Address& src); 274 275 void flds(const Address& src); 276 void fstps(const Address& dst); 277 278 void fldl(const Address& src); 279 void fstpl(const Address& dst); 280 281 void fnstcw(const Address& dst); 282 void fldcw(const Address& src); 283 284 void fistpl(const Address& dst); 285 void fistps(const Address& dst); 286 void fildl(const Address& src); 287 288 void fincstp(); 289 void ffree(const Immediate& index); 290 291 void fsin(); 292 void fcos(); 293 void fptan(); 294 295 void xchgl(Register dst, Register src); 296 297 void cmpl(Register reg, const Immediate& imm); 298 void cmpl(Register reg0, Register reg1); 299 void cmpl(Register reg, const Address& address); 300 301 void cmpl(const Address& address, Register reg); 302 void cmpl(const Address& address, const Immediate& imm); 303 304 void testl(Register reg1, Register reg2); 305 void testl(Register reg, const Immediate& imm); 306 307 void andl(Register dst, const Immediate& imm); 308 void andl(Register dst, Register src); 309 310 void orl(Register dst, const Immediate& imm); 311 void orl(Register dst, Register src); 312 313 void xorl(Register dst, Register src); 314 315 void addl(Register dst, Register src); 316 void addl(Register reg, const Immediate& imm); 317 void addl(Register reg, const Address& address); 318 319 void addl(const Address& address, Register reg); 320 void addl(const Address& address, const Immediate& imm); 321 322 void adcl(Register dst, Register src); 323 void adcl(Register reg, const Immediate& imm); 324 void adcl(Register dst, const Address& address); 325 326 void subl(Register dst, Register src); 327 void subl(Register reg, const Immediate& imm); 328 void subl(Register reg, const Address& address); 329 330 void cdq(); 331 332 void idivl(Register reg); 333 334 void imull(Register dst, Register src); 335 void imull(Register reg, const Immediate& imm); 336 void imull(Register reg, const Address& address); 337 338 void imull(Register reg); 339 void imull(const Address& address); 340 341 void mull(Register reg); 342 void mull(const Address& address); 343 344 void sbbl(Register dst, Register src); 345 void sbbl(Register reg, const Immediate& imm); 346 void sbbl(Register reg, const Address& address); 347 348 void incl(Register reg); 349 void incl(const Address& address); 350 351 void decl(Register reg); 352 void decl(const Address& address); 353 354 void shll(Register reg, const Immediate& imm); 355 void shll(Register operand, Register shifter); 356 void shrl(Register reg, const Immediate& imm); 357 void shrl(Register operand, Register shifter); 358 void sarl(Register reg, const Immediate& imm); 359 void sarl(Register operand, Register shifter); 360 void shld(Register dst, Register src); 361 362 void negl(Register reg); 363 void notl(Register reg); 364 365 void enter(const Immediate& imm); 366 void leave(); 367 368 void ret(); 369 void ret(const Immediate& imm); 370 371 void nop(); 372 void int3(); 373 void hlt(); 374 375 void j(Condition condition, Label* label); 376 377 void jmp(Register reg); 378 void jmp(Label* label); 379 380 void lock(); 381 void cmpxchgl(const Address& address, Register reg); 382 383 /* 384 * Macros for High-level operations. 385 */ 386 void AddImmediate(Register reg, const Immediate& imm); 387 388 void LoadDoubleConstant(XmmRegister dst, double value); 389 390 void DoubleNegate(XmmRegister d); 391 void FloatNegate(XmmRegister f); 392 393 void DoubleAbs(XmmRegister reg); 394 395 void LockCmpxchgl(const Address& address, Register reg) { 396 lock(); 397 cmpxchgl(address, reg); 398 } 399 400 /* 401 * Misc. functionality 402 */ 403 int PreferredLoopAlignment() { return 16; } 404 void Align(int alignment, int offset); 405 void Bind(Label* label); 406 407 int CodeSize() const { return buffer_.Size(); } 408 409 void FinalizeInstructions(const MemoryRegion& region) { 410 buffer_.FinalizeInstructions(region); 411 } 412 413 // Debugging and bringup support. 414 void Stop(const char* message); 415 void Unimplemented(const char* message); 416 void Untested(const char* message); 417 void Unreachable(const char* message); 418 419 static void InitializeMemoryWithBreakpoints(byte* data, size_t length); 420 421 private: 422 AssemblerBuffer buffer_; 423 424 inline void EmitUint8(uint8_t value); 425 inline void EmitInt32(int32_t value); 426 inline void EmitRegisterOperand(int rm, int reg); 427 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg); 428 inline void EmitFixup(AssemblerFixup* fixup); 429 inline void EmitOperandSizeOverride(); 430 431 void EmitOperand(int rm, const Operand& operand); 432 void EmitImmediate(const Immediate& imm); 433 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate); 434 void EmitLabel(Label* label, int instruction_size); 435 void EmitLabelLink(Label* label); 436 void EmitNearLabelLink(Label* label); 437 438 void EmitGenericShift(int rm, Register reg, const Immediate& imm); 439 void EmitGenericShift(int rm, Register operand, Register shifter); 440 441 DISALLOW_COPY_AND_ASSIGN(Assembler); 442}; 443 444 445inline void Assembler::EmitUint8(uint8_t value) { 446 buffer_.Emit<uint8_t>(value); 447} 448 449 450inline void Assembler::EmitInt32(int32_t value) { 451 buffer_.Emit<int32_t>(value); 452} 453 454 455inline void Assembler::EmitRegisterOperand(int rm, int reg) { 456 CHECK_GE(rm, 0); 457 CHECK_LT(rm, 8); 458 buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg); 459} 460 461 462inline void Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) { 463 EmitRegisterOperand(rm, static_cast<Register>(reg)); 464} 465 466 467inline void Assembler::EmitFixup(AssemblerFixup* fixup) { 468 buffer_.EmitFixup(fixup); 469} 470 471 472inline void Assembler::EmitOperandSizeOverride() { 473 EmitUint8(0x66); 474} 475 476} // namespace art 477 478#endif // ART_SRC_ASSEMBLER_X86_H_ 479