OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 // |
| 5 // Modified by the Subzero authors. |
| 6 // |
| 7 //===- subzero/src/assembler_ia32.h - Assembler for x86-32 ----------------===// |
| 8 // |
| 9 // The Subzero Code Generator |
| 10 // |
| 11 // This file is distributed under the University of Illinois Open Source |
| 12 // License. See LICENSE.TXT for details. |
| 13 // |
| 14 //===----------------------------------------------------------------------===// |
| 15 // |
| 16 // This file implements the Assembler class for x86-32. |
| 17 // |
| 18 //===----------------------------------------------------------------------===// |
| 19 |
| 20 #ifndef SUBZERO_SRC_ASSEMBLER_IA32_H_ |
| 21 #define SUBZERO_SRC_ASSEMBLER_IA32_H_ |
| 22 |
| 23 #include "IceDefs.h" |
| 24 #include "IceTypes.h" |
| 25 #include "IceUtils.h" |
| 26 |
| 27 #include "assembler.h" |
| 28 #include "assembler_constants_ia32.h" |
| 29 // Hmm, assembler_ia32.h includes IceInstX8632.h, but IceInstX8632.cpp includes |
| 30 // assembler_ia32.h. Or we can move the BrCond out to, or some other |
| 31 // common group of enums assembler_constants_ia32.h. |
| 32 |
| 33 namespace Ice { |
| 34 |
| 35 class Assembler; |
| 36 class ConstantRelocatable; |
| 37 |
| 38 namespace x86 { |
| 39 |
| 40 class DisplacementRelocation : public AssemblerFixup { |
| 41 public: |
| 42 static DisplacementRelocation *create(Assembler *Asm, FixupKind Kind, |
| 43 const ConstantRelocatable *Sym) { |
| 44 return new (Asm->Allocate<DisplacementRelocation>()) |
| 45 DisplacementRelocation(Kind, Sym); |
| 46 } |
| 47 |
| 48 void Process(const MemoryRegion ®ion, intptr_t position) { |
| 49 (void)region; |
| 50 (void)position; |
| 51 llvm_unreachable("We might not be using this Process() method later."); |
| 52 } |
| 53 |
| 54 private: |
| 55 DisplacementRelocation(FixupKind Kind, const ConstantRelocatable *Sym) |
| 56 : AssemblerFixup(Kind, Sym) {} |
| 57 }; |
| 58 |
| 59 class Immediate { |
| 60 public: |
| 61 explicit Immediate(int32_t value) : value_(value) {} |
| 62 |
| 63 Immediate(const Immediate &other) : value_(other.value_) {} |
| 64 |
| 65 int32_t value() const { return value_; } |
| 66 |
| 67 bool is_int8() const { return Utils::IsInt(8, value_); } |
| 68 bool is_uint8() const { return Utils::IsUint(8, value_); } |
| 69 bool is_uint16() const { return Utils::IsUint(16, value_); } |
| 70 |
| 71 private: |
| 72 const int32_t value_; |
| 73 |
| 74 // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Immediate) once the mac |
| 75 // build issue is resolved. |
| 76 // And remove the unnecessary copy constructor. |
| 77 }; |
| 78 |
| 79 class Operand { |
| 80 public: |
| 81 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; } |
| 82 |
| 83 Register rm() const { return static_cast<Register>(encoding_at(0) & 7); } |
| 84 |
| 85 ScaleFactor scale() const { |
| 86 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); |
| 87 } |
| 88 |
| 89 Register index() const { |
| 90 return static_cast<Register>((encoding_at(1) >> 3) & 7); |
| 91 } |
| 92 |
| 93 Register base() const { return static_cast<Register>(encoding_at(1) & 7); } |
| 94 |
| 95 int8_t disp8() const { |
| 96 assert(length_ >= 2); |
| 97 return static_cast<int8_t>(encoding_[length_ - 1]); |
| 98 } |
| 99 |
| 100 int32_t disp32() const { |
| 101 assert(length_ >= 5); |
| 102 return bit_copy<int32_t>(encoding_[length_ - 4]); |
| 103 } |
| 104 |
| 105 AssemblerFixup *fixup() const { return fixup_; } |
| 106 |
| 107 Operand(const Operand &other) : length_(other.length_), fixup_(other.fixup_) { |
| 108 memmove(&encoding_[0], &other.encoding_[0], other.length_); |
| 109 } |
| 110 |
| 111 Operand &operator=(const Operand &other) { |
| 112 length_ = other.length_; |
| 113 fixup_ = other.fixup_; |
| 114 memmove(&encoding_[0], &other.encoding_[0], other.length_); |
| 115 return *this; |
| 116 } |
| 117 |
| 118 protected: |
| 119 Operand() : length_(0), fixup_(NULL) {} // Needed by subclass Address. |
| 120 |
| 121 void SetModRM(int mod, Register rm) { |
| 122 assert((mod & ~3) == 0); |
| 123 encoding_[0] = (mod << 6) | rm; |
| 124 length_ = 1; |
| 125 } |
| 126 |
| 127 void SetSIB(ScaleFactor scale, Register index, Register base) { |
| 128 assert(length_ == 1); |
| 129 assert((scale & ~3) == 0); |
| 130 encoding_[1] = (scale << 6) | (index << 3) | base; |
| 131 length_ = 2; |
| 132 } |
| 133 |
| 134 void SetDisp8(int8_t disp) { |
| 135 assert(length_ == 1 || length_ == 2); |
| 136 encoding_[length_++] = static_cast<uint8_t>(disp); |
| 137 } |
| 138 |
| 139 void SetDisp32(int32_t disp) { |
| 140 assert(length_ == 1 || length_ == 2); |
| 141 intptr_t disp_size = sizeof(disp); |
| 142 memmove(&encoding_[length_], &disp, disp_size); |
| 143 length_ += disp_size; |
| 144 } |
| 145 |
| 146 void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; } |
| 147 |
| 148 private: |
| 149 uint8_t length_; |
| 150 uint8_t encoding_[6]; |
| 151 uint8_t padding_; |
| 152 AssemblerFixup *fixup_; |
| 153 |
| 154 explicit Operand(Register reg) : fixup_(NULL) { SetModRM(3, reg); } |
| 155 |
| 156 // Get the operand encoding byte at the given index. |
| 157 uint8_t encoding_at(intptr_t index) const { |
| 158 assert(index >= 0 && index < length_); |
| 159 return encoding_[index]; |
| 160 } |
| 161 |
| 162 // Returns whether or not this operand is really the given register in |
| 163 // disguise. Used from the assembler to generate better encodings. |
| 164 bool IsRegister(Register reg) const { |
| 165 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. |
| 166 && ((encoding_[0] & 0x07) == reg); // Register codes match. |
| 167 } |
| 168 |
| 169 friend class AssemblerX86; |
| 170 }; |
| 171 |
| 172 class Address : public Operand { |
| 173 public: |
| 174 Address(Register base, int32_t disp) { |
| 175 if (disp == 0 && base != EBP) { |
| 176 SetModRM(0, base); |
| 177 if (base == ESP) |
| 178 SetSIB(TIMES_1, ESP, base); |
| 179 } else if (Utils::IsInt(8, disp)) { |
| 180 SetModRM(1, base); |
| 181 if (base == ESP) |
| 182 SetSIB(TIMES_1, ESP, base); |
| 183 SetDisp8(disp); |
| 184 } else { |
| 185 SetModRM(2, base); |
| 186 if (base == ESP) |
| 187 SetSIB(TIMES_1, ESP, base); |
| 188 SetDisp32(disp); |
| 189 } |
| 190 } |
| 191 |
| 192 Address(Register index, ScaleFactor scale, int32_t disp) { |
| 193 assert(index != ESP); // Illegal addressing mode. |
| 194 SetModRM(0, ESP); |
| 195 SetSIB(scale, index, EBP); |
| 196 SetDisp32(disp); |
| 197 } |
| 198 |
| 199 Address(Register base, Register index, ScaleFactor scale, int32_t disp) { |
| 200 assert(index != ESP); // Illegal addressing mode. |
| 201 if (disp == 0 && base != EBP) { |
| 202 SetModRM(0, ESP); |
| 203 SetSIB(scale, index, base); |
| 204 } else if (Utils::IsInt(8, disp)) { |
| 205 SetModRM(1, ESP); |
| 206 SetSIB(scale, index, base); |
| 207 SetDisp8(disp); |
| 208 } else { |
| 209 SetModRM(2, ESP); |
| 210 SetSIB(scale, index, base); |
| 211 SetDisp32(disp); |
| 212 } |
| 213 } |
| 214 |
| 215 Address(const Address &other) : Operand(other) {} |
| 216 |
| 217 Address &operator=(const Address &other) { |
| 218 Operand::operator=(other); |
| 219 return *this; |
| 220 } |
| 221 |
| 222 static Address Absolute(const uintptr_t addr, AssemblerFixup *fixup) { |
| 223 Address result; |
| 224 result.SetModRM(0, EBP); |
| 225 result.SetDisp32(addr); |
| 226 result.SetFixup(fixup); |
| 227 return result; |
| 228 } |
| 229 |
| 230 private: |
| 231 Address() {} // Needed by Address::Absolute. |
| 232 }; |
| 233 |
| 234 class Label { |
| 235 public: |
| 236 Label() : position_(0), num_unresolved_(0) { |
| 237 #ifdef DEBUG |
| 238 for (int i = 0; i < kMaxUnresolvedBranches; i++) { |
| 239 unresolved_near_positions_[i] = -1; |
| 240 } |
| 241 #endif // DEBUG |
| 242 } |
| 243 |
| 244 ~Label() { |
| 245 // Assert if label is being destroyed with unresolved branches pending. |
| 246 assert(!IsLinked()); |
| 247 assert(!HasNear()); |
| 248 } |
| 249 |
| 250 // TODO(jvoung): why are labels offset by this? |
| 251 static const uint32_t kWordSize = sizeof(uint32_t); |
| 252 |
| 253 // Returns the position for bound labels (branches that come after this |
| 254 // are considered backward branches). Cannot be used for unused or linked |
| 255 // labels. |
| 256 intptr_t Position() const { |
| 257 assert(IsBound()); |
| 258 return -position_ - kWordSize; |
| 259 } |
| 260 |
| 261 // Returns the position of an earlier branch instruction that was linked |
| 262 // to this label (branches that use this are considered forward branches). |
| 263 // The linked instructions form a linked list, of sorts, using the |
| 264 // instruction's displacement field for the location of the next |
| 265 // instruction that is also linked to this label. |
| 266 intptr_t LinkPosition() const { |
| 267 assert(IsLinked()); |
| 268 return position_ - kWordSize; |
| 269 } |
| 270 |
| 271 // Returns the position of an earlier branch instruction which |
| 272 // assumes that this label is "near", and bumps iterator to the |
| 273 // next near position. |
| 274 intptr_t NearPosition() { |
| 275 assert(HasNear()); |
| 276 return unresolved_near_positions_[--num_unresolved_]; |
| 277 } |
| 278 |
| 279 bool IsBound() const { return position_ < 0; } |
| 280 bool IsLinked() const { return position_ > 0; } |
| 281 bool IsUnused() const { return (position_ == 0) && (num_unresolved_ == 0); } |
| 282 bool HasNear() const { return num_unresolved_ != 0; } |
| 283 |
| 284 private: |
| 285 void BindTo(intptr_t position) { |
| 286 assert(!IsBound()); |
| 287 assert(!HasNear()); |
| 288 position_ = -position - kWordSize; |
| 289 assert(IsBound()); |
| 290 } |
| 291 |
| 292 void LinkTo(intptr_t position) { |
| 293 assert(!IsBound()); |
| 294 position_ = position + kWordSize; |
| 295 assert(IsLinked()); |
| 296 } |
| 297 |
| 298 void NearLinkTo(intptr_t position) { |
| 299 assert(!IsBound()); |
| 300 assert(num_unresolved_ < kMaxUnresolvedBranches); |
| 301 unresolved_near_positions_[num_unresolved_++] = position; |
| 302 } |
| 303 |
| 304 static const int kMaxUnresolvedBranches = 20; |
| 305 |
| 306 intptr_t position_; |
| 307 intptr_t num_unresolved_; |
| 308 intptr_t unresolved_near_positions_[kMaxUnresolvedBranches]; |
| 309 |
| 310 friend class AssemblerX86; |
| 311 Label(const Label &) LLVM_DELETED_FUNCTION; |
| 312 Label &operator=(const Label &) LLVM_DELETED_FUNCTION; |
| 313 }; |
| 314 |
| 315 class AssemblerX86 : public Assembler { |
| 316 public: |
| 317 explicit AssemblerX86(bool use_far_branches = false) : buffer_(*this) { |
| 318 // This mode is only needed and implemented for MIPS and ARM. |
| 319 assert(!use_far_branches); |
| 320 } |
| 321 ~AssemblerX86() {} |
| 322 |
| 323 static const bool kNearJump = true; |
| 324 static const bool kFarJump = false; |
| 325 |
| 326 // For integer operations that are strict on type. |
| 327 typedef void (AssemblerX86::*EmitRegByteR)(Register, ByteRegister); |
| 328 typedef void (AssemblerX86::*EmitRegReg)(Register, Register); |
| 329 typedef void (AssemblerX86::*EmitRegAddr)(Register, const Address &); |
| 330 |
| 331 // For the integer operations that are less strict on type. |
| 332 // Make a version that is independent of the type and fudge a little |
| 333 // and consider ByteRegister the same as Register. |
| 334 typedef void (AssemblerX86::*EmitTyRegReg)(Type, Register, Register); |
| 335 typedef void (AssemblerX86::*EmitTyRegImm)(Type, Register, const Immediate &); |
| 336 typedef void (AssemblerX86::*EmitTyRegAddr)(Type, Register, const Address &); |
| 337 typedef void (AssemblerX86::*EmitTyAddrReg)(Type, const Address &, Register); |
| 338 typedef void (AssemblerX86::*EmitTyAddrImm)(Type, const Address &, |
| 339 const Immediate &); |
| 340 |
| 341 // For XMM operations. |
| 342 typedef void (AssemblerX86::*EmitXmmXmm)(XmmRegister, XmmRegister); |
| 343 typedef void (AssemblerX86::*EmitXmmAddr)(XmmRegister, const Address &); |
| 344 typedef void (AssemblerX86::*EmitAddrXmm)(const Address &, XmmRegister); |
| 345 |
| 346 typedef void (AssemblerX86::*EmitTyXmmXmm)(Type, XmmRegister, XmmRegister); |
| 347 typedef void (AssemblerX86::*EmitTyXmmAddr)(Type, XmmRegister, |
| 348 const Address &); |
| 349 typedef void (AssemblerX86::*EmitTyAddrXmm)(Type, const Address &, |
| 350 XmmRegister); |
| 351 |
| 352 /* |
| 353 * Emit Machine Instructions. |
| 354 */ |
| 355 void call(Register reg); |
| 356 void call(const Address &address); |
| 357 void call(Label *label); |
| 358 void call(const ConstantRelocatable *label); |
| 359 |
| 360 static const intptr_t kCallExternalLabelSize = 5; |
| 361 |
| 362 void pushl(Register reg); |
| 363 void pushl(const Address &address); |
| 364 void pushl(const Immediate &imm); |
| 365 |
| 366 void popl(Register reg); |
| 367 void popl(const Address &address); |
| 368 |
| 369 void pushal(); |
| 370 void popal(); |
| 371 |
| 372 void setcc(Condition condition, ByteRegister dst); |
| 373 |
| 374 void movl(Register dst, const Immediate &src); |
| 375 void movl(Register dst, Register src); |
| 376 |
| 377 void movl(Register dst, const Address &src); |
| 378 void movl(const Address &dst, Register src); |
| 379 void movl(const Address &dst, const Immediate &imm); |
| 380 |
| 381 void movzxb(Register dst, ByteRegister src); |
| 382 void movzxb(Register dst, const Address &src); |
| 383 void movsxb(Register dst, ByteRegister src); |
| 384 void movsxb(Register dst, const Address &src); |
| 385 |
| 386 void movb(ByteRegister dst, const Address &src); |
| 387 void movb(const Address &dst, ByteRegister src); |
| 388 void movb(const Address &dst, const Immediate &imm); |
| 389 |
| 390 void movzxw(Register dst, Register src); |
| 391 void movzxw(Register dst, const Address &src); |
| 392 void movsxw(Register dst, Register src); |
| 393 void movsxw(Register dst, const Address &src); |
| 394 void movw(Register dst, const Address &src); |
| 395 void movw(const Address &dst, Register src); |
| 396 |
| 397 void leal(Register dst, const Address &src); |
| 398 |
| 399 void cmov(Condition cond, Register dst, Register src); |
| 400 |
| 401 void rep_movsb(); |
| 402 |
| 403 void movss(XmmRegister dst, const Address &src); |
| 404 void movss(const Address &dst, XmmRegister src); |
| 405 void movss(XmmRegister dst, XmmRegister src); |
| 406 |
| 407 void movd(XmmRegister dst, Register src); |
| 408 void movd(Register dst, XmmRegister src); |
| 409 |
| 410 void movq(const Address &dst, XmmRegister src); |
| 411 void movq(XmmRegister dst, const Address &src); |
| 412 |
| 413 void addss(XmmRegister dst, XmmRegister src); |
| 414 void addss(XmmRegister dst, const Address &src); |
| 415 void subss(XmmRegister dst, XmmRegister src); |
| 416 void subss(XmmRegister dst, const Address &src); |
| 417 void mulss(XmmRegister dst, XmmRegister src); |
| 418 void mulss(XmmRegister dst, const Address &src); |
| 419 void divss(XmmRegister dst, XmmRegister src); |
| 420 void divss(XmmRegister dst, const Address &src); |
| 421 |
| 422 void movsd(XmmRegister dst, const Address &src); |
| 423 void movsd(const Address &dst, XmmRegister src); |
| 424 void movsd(XmmRegister dst, XmmRegister src); |
| 425 |
| 426 void movaps(XmmRegister dst, XmmRegister src); |
| 427 |
| 428 void movups(XmmRegister dst, const Address &src); |
| 429 void movups(const Address &dst, XmmRegister src); |
| 430 |
| 431 void addsd(XmmRegister dst, XmmRegister src); |
| 432 void addsd(XmmRegister dst, const Address &src); |
| 433 void subsd(XmmRegister dst, XmmRegister src); |
| 434 void subsd(XmmRegister dst, const Address &src); |
| 435 void mulsd(XmmRegister dst, XmmRegister src); |
| 436 void mulsd(XmmRegister dst, const Address &src); |
| 437 void divsd(XmmRegister dst, XmmRegister src); |
| 438 void divsd(XmmRegister dst, const Address &src); |
| 439 |
| 440 void padd(Type Ty, XmmRegister dst, XmmRegister src); |
| 441 void padd(Type Ty, XmmRegister dst, const Address &src); |
| 442 void psub(Type Ty, XmmRegister dst, XmmRegister src); |
| 443 void psub(Type Ty, XmmRegister dst, const Address &src); |
| 444 |
| 445 void addps(XmmRegister dst, XmmRegister src); |
| 446 void addps(XmmRegister dst, const Address &src); |
| 447 void subps(XmmRegister dst, XmmRegister src); |
| 448 void subps(XmmRegister dst, const Address &src); |
| 449 void divps(XmmRegister dst, XmmRegister src); |
| 450 void divps(XmmRegister dst, const Address &src); |
| 451 void mulps(XmmRegister dst, XmmRegister src); |
| 452 void mulps(XmmRegister dst, const Address &src); |
| 453 void minps(XmmRegister dst, XmmRegister src); |
| 454 void maxps(XmmRegister dst, XmmRegister src); |
| 455 void andps(XmmRegister dst, XmmRegister src); |
| 456 void andps(XmmRegister dst, const Address &src); |
| 457 void orps(XmmRegister dst, XmmRegister src); |
| 458 |
| 459 // TODO(jvoung): Use the enum type instead of uint8_t. |
| 460 void cmpps(XmmRegister dst, XmmRegister src, uint8_t CmpCondition); |
| 461 void cmpps(XmmRegister dst, const Address &src, uint8_t CmpCondition); |
| 462 |
| 463 void sqrtps(XmmRegister dst); |
| 464 void rsqrtps(XmmRegister dst); |
| 465 void reciprocalps(XmmRegister dst); |
| 466 void movhlps(XmmRegister dst, XmmRegister src); |
| 467 void movlhps(XmmRegister dst, XmmRegister src); |
| 468 void unpcklps(XmmRegister dst, XmmRegister src); |
| 469 void unpckhps(XmmRegister dst, XmmRegister src); |
| 470 void unpcklpd(XmmRegister dst, XmmRegister src); |
| 471 void unpckhpd(XmmRegister dst, XmmRegister src); |
| 472 |
| 473 void set1ps(XmmRegister dst, Register tmp, const Immediate &imm); |
| 474 void shufps(XmmRegister dst, XmmRegister src, const Immediate &mask); |
| 475 |
| 476 void addpd(XmmRegister dst, XmmRegister src); |
| 477 void subpd(XmmRegister dst, XmmRegister src); |
| 478 void mulpd(XmmRegister dst, XmmRegister src); |
| 479 void divpd(XmmRegister dst, XmmRegister src); |
| 480 void minpd(XmmRegister dst, XmmRegister src); |
| 481 void maxpd(XmmRegister dst, XmmRegister src); |
| 482 void sqrtpd(XmmRegister dst); |
| 483 void cvtps2pd(XmmRegister dst, XmmRegister src); |
| 484 void cvtpd2ps(XmmRegister dst, XmmRegister src); |
| 485 void shufpd(XmmRegister dst, XmmRegister src, const Immediate &mask); |
| 486 |
| 487 void cvtsi2ss(XmmRegister dst, Register src); |
| 488 void cvtsi2sd(XmmRegister dst, Register src); |
| 489 |
| 490 void cvtss2si(Register dst, XmmRegister src); |
| 491 void cvtss2sd(XmmRegister dst, XmmRegister src); |
| 492 |
| 493 void cvtsd2si(Register dst, XmmRegister src); |
| 494 void cvtsd2ss(XmmRegister dst, XmmRegister src); |
| 495 |
| 496 void cvttss2si(Register dst, XmmRegister src); |
| 497 void cvttsd2si(Register dst, XmmRegister src); |
| 498 |
| 499 void cvtdq2pd(XmmRegister dst, XmmRegister src); |
| 500 |
| 501 void ucomiss(XmmRegister a, XmmRegister b); |
| 502 void ucomiss(XmmRegister a, const Address &b); |
| 503 void ucomisd(XmmRegister a, XmmRegister b); |
| 504 void ucomisd(XmmRegister a, const Address &b); |
| 505 |
| 506 void movmskpd(Register dst, XmmRegister src); |
| 507 void movmskps(Register dst, XmmRegister src); |
| 508 |
| 509 void sqrtsd(XmmRegister dst, const Address &src); |
| 510 void sqrtsd(XmmRegister dst, XmmRegister src); |
| 511 void sqrtss(XmmRegister dst, const Address &src); |
| 512 void sqrtss(XmmRegister dst, XmmRegister src); |
| 513 |
| 514 void xorpd(XmmRegister dst, const Address &src); |
| 515 void xorpd(XmmRegister dst, XmmRegister src); |
| 516 void xorps(XmmRegister dst, const Address &src); |
| 517 void xorps(XmmRegister dst, XmmRegister src); |
| 518 |
| 519 void andpd(XmmRegister dst, const Address &src); |
| 520 void andpd(XmmRegister dst, XmmRegister src); |
| 521 |
| 522 void orpd(XmmRegister dst, XmmRegister src); |
| 523 |
| 524 void pextrd(Register dst, XmmRegister src, const Immediate &imm); |
| 525 void pmovsxdq(XmmRegister dst, XmmRegister src); |
| 526 void pcmpeqq(XmmRegister dst, XmmRegister src); |
| 527 |
| 528 void pxor(XmmRegister dst, XmmRegister src); |
| 529 |
| 530 enum RoundingMode { |
| 531 kRoundToNearest = 0x0, |
| 532 kRoundDown = 0x1, |
| 533 kRoundUp = 0x2, |
| 534 kRoundToZero = 0x3 |
| 535 }; |
| 536 void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode); |
| 537 |
| 538 void flds(const Address &src); |
| 539 void fstps(const Address &dst); |
| 540 |
| 541 void fldl(const Address &src); |
| 542 void fstpl(const Address &dst); |
| 543 |
| 544 void fnstcw(const Address &dst); |
| 545 void fldcw(const Address &src); |
| 546 |
| 547 void fistpl(const Address &dst); |
| 548 void fistps(const Address &dst); |
| 549 void fildl(const Address &src); |
| 550 void filds(const Address &src); |
| 551 |
| 552 void fincstp(); |
| 553 |
| 554 void xchgl(Register dst, Register src); |
| 555 |
| 556 void cmp(Type Ty, Register reg, const Immediate &imm); |
| 557 void cmp(Type Ty, Register reg0, Register reg1); |
| 558 void cmp(Type Ty, Register reg, const Address &address); |
| 559 |
| 560 void cmp(Type Ty, const Address &address, Register reg); |
| 561 void cmp(Type Ty, const Address &address, const Immediate &imm); |
| 562 |
| 563 void testl(Register reg1, Register reg2); |
| 564 void testl(Register reg, const Immediate &imm); |
| 565 |
| 566 void _and(Type Ty, Register dst, const Immediate &imm); |
| 567 void _and(Type Ty, Register dst, Register src); |
| 568 void _and(Type Ty, Register dst, const Address &address); |
| 569 |
| 570 void _or(Type Ty, Register dst, const Immediate &imm); |
| 571 void _or(Type Ty, Register dst, Register src); |
| 572 void _or(Type Ty, Register dst, const Address &address); |
| 573 |
| 574 void _xor(Type Ty, Register dst, const Immediate &imm); |
| 575 void _xor(Type Ty, Register dst, Register src); |
| 576 void _xor(Type Ty, Register dst, const Address &address); |
| 577 |
| 578 // We fudge a little, and use Register for ByteRegister as well. |
| 579 void add(Type Ty, Register dst, Register src); |
| 580 void add(Type Ty, Register reg, const Immediate &imm); |
| 581 void add(Type Ty, Register reg, const Address &address); |
| 582 |
| 583 void add(Type Ty, const Address &address, Register reg); |
| 584 void add(Type Ty, const Address &address, const Immediate &imm); |
| 585 |
| 586 void adc(Type Ty, Register dst, Register src); |
| 587 void adc(Type Ty, Register reg, const Immediate &imm); |
| 588 void adc(Type Ty, Register dst, const Address &address); |
| 589 |
| 590 void sub(Type Ty, Register dst, Register src); |
| 591 void sub(Type Ty, Register reg, const Immediate &imm); |
| 592 void sub(Type Ty, Register reg, const Address &address); |
| 593 |
| 594 void cbw(); |
| 595 void cwd(); |
| 596 void cdq(); |
| 597 |
| 598 void idivl(Register reg); |
| 599 |
| 600 void imull(Register dst, Register src); |
| 601 void imull(Register reg, const Immediate &imm); |
| 602 void imull(Register reg, const Address &address); |
| 603 |
| 604 void imull(Register reg); |
| 605 void imull(const Address &address); |
| 606 |
| 607 void mull(Register reg); |
| 608 void mull(const Address &address); |
| 609 |
| 610 void sbb(Type Ty, Register dst, Register src); |
| 611 void sbb(Type Ty, Register reg, const Immediate &imm); |
| 612 void sbb(Type Ty, Register reg, const Address &address); |
| 613 |
| 614 void incl(Register reg); |
| 615 void incl(const Address &address); |
| 616 |
| 617 void decl(Register reg); |
| 618 void decl(const Address &address); |
| 619 |
| 620 void shll(Register reg, const Immediate &imm); |
| 621 void shll(Register operand, Register shifter); |
| 622 void shll(const Address &operand, Register shifter); |
| 623 void shrl(Register reg, const Immediate &imm); |
| 624 void shrl(Register operand, Register shifter); |
| 625 void sarl(Register reg, const Immediate &imm); |
| 626 void sarl(Register operand, Register shifter); |
| 627 void sarl(const Address &address, Register shifter); |
| 628 void shld(Register dst, Register src); |
| 629 void shld(Register dst, Register src, const Immediate &imm); |
| 630 void shld(const Address &operand, Register src); |
| 631 void shrd(Register dst, Register src); |
| 632 void shrd(Register dst, Register src, const Immediate &imm); |
| 633 void shrd(const Address &dst, Register src); |
| 634 |
| 635 void negl(Register reg); |
| 636 void notl(Register reg); |
| 637 |
| 638 void bsrl(Register dst, Register src); |
| 639 |
| 640 void bt(Register base, Register offset); |
| 641 |
| 642 void enter(const Immediate &imm); |
| 643 void leave(); |
| 644 |
| 645 void ret(); |
| 646 void ret(const Immediate &imm); |
| 647 |
| 648 // 'size' indicates size in bytes and must be in the range 1..8. |
| 649 void nop(int size = 1); |
| 650 void int3(); |
| 651 // TODO(jvoung): should Subzero just use hlt instead of ud2? |
| 652 void hlt(); |
| 653 |
| 654 void j(Condition condition, Label *label, bool near = kFarJump); |
| 655 void j(Condition condition, const ConstantRelocatable *label); |
| 656 |
| 657 void jmp(Register reg); |
| 658 void jmp(Label *label, bool near = kFarJump); |
| 659 void jmp(const ConstantRelocatable *label); |
| 660 |
| 661 void lock(); |
| 662 void cmpxchgl(const Address &address, Register reg); |
| 663 |
| 664 void LockCmpxchgl(const Address &address, Register reg) { |
| 665 lock(); |
| 666 cmpxchgl(address, reg); |
| 667 } |
| 668 |
| 669 intptr_t PreferredLoopAlignment() { return 16; } |
| 670 void Align(intptr_t alignment, intptr_t offset); |
| 671 void Bind(Label *label); |
| 672 |
| 673 intptr_t CodeSize() const { return buffer_.Size(); } |
| 674 |
| 675 void FinalizeInstructions(const MemoryRegion ®ion) { |
| 676 buffer_.FinalizeInstructions(region); |
| 677 } |
| 678 |
| 679 // Expose the buffer, for bringup... |
| 680 intptr_t GetPosition() const { return buffer_.GetPosition(); } |
| 681 template <typename T> T LoadBuffer(intptr_t position) const { |
| 682 return buffer_.Load<T>(position); |
| 683 } |
| 684 AssemblerFixup *GetLatestFixup() const { return buffer_.GetLatestFixup(); } |
| 685 |
| 686 private: |
| 687 inline void EmitUint8(uint8_t value); |
| 688 inline void EmitInt32(int32_t value); |
| 689 inline void EmitRegisterOperand(int rm, int reg); |
| 690 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg); |
| 691 inline void EmitFixup(AssemblerFixup *fixup); |
| 692 inline void EmitOperandSizeOverride(); |
| 693 |
| 694 void EmitOperand(int rm, const Operand &operand); |
| 695 void EmitImmediate(const Immediate &imm); |
| 696 void EmitComplexI8(int rm, const Operand &operand, |
| 697 const Immediate &immediate); |
| 698 void EmitComplex(int rm, const Operand &operand, const Immediate &immediate); |
| 699 void EmitLabel(Label *label, intptr_t instruction_size); |
| 700 void EmitLabelLink(Label *label); |
| 701 void EmitNearLabelLink(Label *label); |
| 702 |
| 703 void EmitGenericShift(int rm, Register reg, const Immediate &imm); |
| 704 void EmitGenericShift(int rm, const Operand &operand, Register shifter); |
| 705 |
| 706 AssemblerBuffer buffer_; |
| 707 |
| 708 // DISALLOW_ALLOCATION(); // disables operator new. |
| 709 AssemblerX86(const AssemblerX86 &) LLVM_DELETED_FUNCTION; |
| 710 AssemblerX86 &operator=(const AssemblerX86 &) LLVM_DELETED_FUNCTION; |
| 711 }; |
| 712 |
| 713 inline void AssemblerX86::EmitUint8(uint8_t value) { |
| 714 buffer_.Emit<uint8_t>(value); |
| 715 } |
| 716 |
| 717 inline void AssemblerX86::EmitInt32(int32_t value) { |
| 718 buffer_.Emit<int32_t>(value); |
| 719 } |
| 720 |
| 721 inline void AssemblerX86::EmitRegisterOperand(int rm, int reg) { |
| 722 assert(rm >= 0 && rm < 8); |
| 723 buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg); |
| 724 } |
| 725 |
| 726 inline void AssemblerX86::EmitXmmRegisterOperand(int rm, XmmRegister reg) { |
| 727 EmitRegisterOperand(rm, static_cast<Register>(reg)); |
| 728 } |
| 729 |
| 730 inline void AssemblerX86::EmitFixup(AssemblerFixup *fixup) { |
| 731 buffer_.EmitFixup(fixup); |
| 732 } |
| 733 |
| 734 inline void AssemblerX86::EmitOperandSizeOverride() { EmitUint8(0x66); } |
| 735 |
| 736 } // end of namespace x86 |
| 737 } // end of namespace Ice |
| 738 |
| 739 #endif // SUBZERO_SRC_ASSEMBLER_IA32_H_ |
OLD | NEW |