| OLD | NEW |
| 1 //===- subzero/src/assembler_ia32.h - Assembler for x86-32 ------*- C++ -*-===// | 1 //===- subzero/src/assembler_ia32.h - Assembler for x86-32 ------*- C++ -*-===// |
| 2 // | 2 // |
| 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 4 // for details. All rights reserved. Use of this source code is governed by a | 4 // for details. All rights reserved. Use of this source code is governed by a |
| 5 // BSD-style license that can be found in the LICENSE file. | 5 // BSD-style license that can be found in the LICENSE file. |
| 6 // | 6 // |
| 7 // Modified by the Subzero authors. | 7 // Modified by the Subzero authors. |
| 8 // | 8 // |
| 9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
| 10 // | 10 // |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 | 31 |
| 32 #include "assembler.h" | 32 #include "assembler.h" |
| 33 | 33 |
| 34 namespace Ice { | 34 namespace Ice { |
| 35 | 35 |
| 36 using RegX8632::GPRRegister; | 36 using RegX8632::GPRRegister; |
| 37 using RegX8632::XmmRegister; | 37 using RegX8632::XmmRegister; |
| 38 using RegX8632::ByteRegister; | 38 using RegX8632::ByteRegister; |
| 39 using RegX8632::X87STRegister; | 39 using RegX8632::X87STRegister; |
| 40 | 40 |
| 41 namespace x86 { | 41 namespace X8632 { |
| 42 | 42 |
| 43 const int MAX_NOP_SIZE = 8; | 43 const int MAX_NOP_SIZE = 8; |
| 44 | 44 |
| 45 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; | 45 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; |
| 46 | 46 |
| 47 class Immediate { | 47 class Immediate { |
| 48 Immediate(const Immediate &) = delete; | 48 Immediate(const Immediate &) = delete; |
| 49 Immediate &operator=(const Immediate &) = delete; | 49 Immediate &operator=(const Immediate &) = delete; |
| 50 | 50 |
| 51 public: | 51 public: |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 return encoding_[index]; | 163 return encoding_[index]; |
| 164 } | 164 } |
| 165 | 165 |
| 166 // Returns whether or not this operand is really the given register in | 166 // Returns whether or not this operand is really the given register in |
| 167 // disguise. Used from the assembler to generate better encodings. | 167 // disguise. Used from the assembler to generate better encodings. |
| 168 bool IsRegister(GPRRegister reg) const { | 168 bool IsRegister(GPRRegister reg) const { |
| 169 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. | 169 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. |
| 170 && ((encoding_[0] & 0x07) == reg); // Register codes match. | 170 && ((encoding_[0] & 0x07) == reg); // Register codes match. |
| 171 } | 171 } |
| 172 | 172 |
| 173 friend class AssemblerX86; | 173 friend class AssemblerX8632; |
| 174 }; | 174 }; |
| 175 | 175 |
| 176 class Address : public Operand { | 176 class Address : public Operand { |
| 177 public: | 177 public: |
| 178 Address(const Address &other) : Operand(other) {} | 178 Address(const Address &other) : Operand(other) {} |
| 179 | 179 |
| 180 Address &operator=(const Address &other) { | 180 Address &operator=(const Address &other) { |
| 181 Operand::operator=(other); | 181 Operand::operator=(other); |
| 182 return *this; | 182 return *this; |
| 183 } | 183 } |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 } | 323 } |
| 324 | 324 |
| 325 static const int kMaxUnresolvedBranches = 20; | 325 static const int kMaxUnresolvedBranches = 20; |
| 326 | 326 |
| 327 intptr_t position_; | 327 intptr_t position_; |
| 328 intptr_t num_unresolved_; | 328 intptr_t num_unresolved_; |
| 329 // TODO(stichnot,jvoung): Can this instead be | 329 // TODO(stichnot,jvoung): Can this instead be |
| 330 // llvm::SmallVector<intptr_t, kMaxUnresolvedBranches> ? | 330 // llvm::SmallVector<intptr_t, kMaxUnresolvedBranches> ? |
| 331 intptr_t unresolved_near_positions_[kMaxUnresolvedBranches]; | 331 intptr_t unresolved_near_positions_[kMaxUnresolvedBranches]; |
| 332 | 332 |
| 333 friend class AssemblerX86; | 333 friend class AssemblerX8632; |
| 334 }; | 334 }; |
| 335 | 335 |
| 336 class AssemblerX86 : public Assembler { | 336 class AssemblerX8632 : public Assembler { |
| 337 AssemblerX86(const AssemblerX86 &) = delete; | 337 AssemblerX8632(const AssemblerX8632 &) = delete; |
| 338 AssemblerX86 &operator=(const AssemblerX86 &) = delete; | 338 AssemblerX8632 &operator=(const AssemblerX8632 &) = delete; |
| 339 | 339 |
| 340 public: | 340 public: |
| 341 explicit AssemblerX86(bool use_far_branches = false) : Assembler() { | 341 explicit AssemblerX8632(bool use_far_branches = false) : Assembler() { |
| 342 // This mode is only needed and implemented for MIPS and ARM. | 342 // This mode is only needed and implemented for MIPS and ARM. |
| 343 assert(!use_far_branches); | 343 assert(!use_far_branches); |
| 344 (void)use_far_branches; | 344 (void)use_far_branches; |
| 345 } | 345 } |
| 346 ~AssemblerX86() override; | 346 ~AssemblerX8632() override; |
| 347 | 347 |
| 348 static const bool kNearJump = true; | 348 static const bool kNearJump = true; |
| 349 static const bool kFarJump = false; | 349 static const bool kFarJump = false; |
| 350 | 350 |
| 351 void alignFunction() override; | 351 void alignFunction() override; |
| 352 | 352 |
| 353 SizeT getBundleAlignLog2Bytes() const override { return 5; } | 353 SizeT getBundleAlignLog2Bytes() const override { return 5; } |
| 354 | 354 |
| 355 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override { | 355 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override { |
| 356 static const uint8_t Padding[] = {0xF4}; | 356 static const uint8_t Padding[] = {0xF4}; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 370 void BindCfgNodeLabel(SizeT NodeNumber) override; | 370 void BindCfgNodeLabel(SizeT NodeNumber) override; |
| 371 Label *GetOrCreateLocalLabel(SizeT Number); | 371 Label *GetOrCreateLocalLabel(SizeT Number); |
| 372 void BindLocalLabel(SizeT Number); | 372 void BindLocalLabel(SizeT Number); |
| 373 | 373 |
| 374 bool fixupIsPCRel(FixupKind Kind) const override { | 374 bool fixupIsPCRel(FixupKind Kind) const override { |
| 375 // Currently assuming this is the only PC-rel relocation type used. | 375 // Currently assuming this is the only PC-rel relocation type used. |
| 376 return Kind == llvm::ELF::R_386_PC32; | 376 return Kind == llvm::ELF::R_386_PC32; |
| 377 } | 377 } |
| 378 | 378 |
| 379 // Operations to emit GPR instructions (and dispatch on operand type). | 379 // Operations to emit GPR instructions (and dispatch on operand type). |
| 380 typedef void (AssemblerX86::*TypedEmitGPR)(Type, GPRRegister); | 380 typedef void (AssemblerX8632::*TypedEmitGPR)(Type, GPRRegister); |
| 381 typedef void (AssemblerX86::*TypedEmitAddr)(Type, const Address &); | 381 typedef void (AssemblerX8632::*TypedEmitAddr)(Type, const Address &); |
| 382 struct GPREmitterOneOp { | 382 struct GPREmitterOneOp { |
| 383 TypedEmitGPR Reg; | 383 TypedEmitGPR Reg; |
| 384 TypedEmitAddr Addr; | 384 TypedEmitAddr Addr; |
| 385 }; | 385 }; |
| 386 | 386 |
| 387 typedef void (AssemblerX86::*TypedEmitGPRGPR)(Type, GPRRegister, GPRRegister); | 387 typedef void (AssemblerX8632::*TypedEmitGPRGPR)(Type, GPRRegister, |
| 388 typedef void (AssemblerX86::*TypedEmitGPRAddr)(Type, GPRRegister, | 388 GPRRegister); |
| 389 const Address &); | 389 typedef void (AssemblerX8632::*TypedEmitGPRAddr)(Type, GPRRegister, |
| 390 typedef void (AssemblerX86::*TypedEmitGPRImm)(Type, GPRRegister, | 390 const Address &); |
| 391 const Immediate &); | 391 typedef void (AssemblerX8632::*TypedEmitGPRImm)(Type, GPRRegister, |
| 392 const Immediate &); |
| 392 struct GPREmitterRegOp { | 393 struct GPREmitterRegOp { |
| 393 TypedEmitGPRGPR GPRGPR; | 394 TypedEmitGPRGPR GPRGPR; |
| 394 TypedEmitGPRAddr GPRAddr; | 395 TypedEmitGPRAddr GPRAddr; |
| 395 TypedEmitGPRImm GPRImm; | 396 TypedEmitGPRImm GPRImm; |
| 396 }; | 397 }; |
| 397 | 398 |
| 398 struct GPREmitterShiftOp { | 399 struct GPREmitterShiftOp { |
| 399 // Technically, Addr/GPR and Addr/Imm are also allowed, but */Addr are not. | 400 // Technically, Addr/GPR and Addr/Imm are also allowed, but */Addr are not. |
| 400 // In practice, we always normalize the Dest to a Register first. | 401 // In practice, we always normalize the Dest to a Register first. |
| 401 TypedEmitGPRGPR GPRGPR; | 402 TypedEmitGPRGPR GPRGPR; |
| 402 TypedEmitGPRImm GPRImm; | 403 TypedEmitGPRImm GPRImm; |
| 403 }; | 404 }; |
| 404 | 405 |
| 405 typedef void (AssemblerX86::*TypedEmitGPRGPRImm)(Type, GPRRegister, | 406 typedef void (AssemblerX8632::*TypedEmitGPRGPRImm)(Type, GPRRegister, |
| 406 GPRRegister, | 407 GPRRegister, |
| 407 const Immediate &); | 408 const Immediate &); |
| 408 struct GPREmitterShiftD { | 409 struct GPREmitterShiftD { |
| 409 // Technically AddrGPR and AddrGPRImm are also allowed, but in practice | 410 // Technically AddrGPR and AddrGPRImm are also allowed, but in practice |
| 410 // we always normalize Dest to a Register first. | 411 // we always normalize Dest to a Register first. |
| 411 TypedEmitGPRGPR GPRGPR; | 412 TypedEmitGPRGPR GPRGPR; |
| 412 TypedEmitGPRGPRImm GPRGPRImm; | 413 TypedEmitGPRGPRImm GPRGPRImm; |
| 413 }; | 414 }; |
| 414 | 415 |
| 415 typedef void (AssemblerX86::*TypedEmitAddrGPR)(Type, const Address &, | 416 typedef void (AssemblerX8632::*TypedEmitAddrGPR)(Type, const Address &, |
| 416 GPRRegister); | 417 GPRRegister); |
| 417 typedef void (AssemblerX86::*TypedEmitAddrImm)(Type, const Address &, | 418 typedef void (AssemblerX8632::*TypedEmitAddrImm)(Type, const Address &, |
| 418 const Immediate &); | 419 const Immediate &); |
| 419 struct GPREmitterAddrOp { | 420 struct GPREmitterAddrOp { |
| 420 TypedEmitAddrGPR AddrGPR; | 421 TypedEmitAddrGPR AddrGPR; |
| 421 TypedEmitAddrImm AddrImm; | 422 TypedEmitAddrImm AddrImm; |
| 422 }; | 423 }; |
| 423 | 424 |
| 424 // Operations to emit XMM instructions (and dispatch on operand type). | 425 // Operations to emit XMM instructions (and dispatch on operand type). |
| 425 typedef void (AssemblerX86::*TypedEmitXmmXmm)(Type, XmmRegister, XmmRegister); | 426 typedef void (AssemblerX8632::*TypedEmitXmmXmm)(Type, XmmRegister, |
| 426 typedef void (AssemblerX86::*TypedEmitXmmAddr)(Type, XmmRegister, | 427 XmmRegister); |
| 427 const Address &); | 428 typedef void (AssemblerX8632::*TypedEmitXmmAddr)(Type, XmmRegister, |
| 429 const Address &); |
| 428 struct XmmEmitterRegOp { | 430 struct XmmEmitterRegOp { |
| 429 TypedEmitXmmXmm XmmXmm; | 431 TypedEmitXmmXmm XmmXmm; |
| 430 TypedEmitXmmAddr XmmAddr; | 432 TypedEmitXmmAddr XmmAddr; |
| 431 }; | 433 }; |
| 432 | 434 |
| 433 typedef void (AssemblerX86::*EmitXmmXmm)(XmmRegister, XmmRegister); | 435 typedef void (AssemblerX8632::*EmitXmmXmm)(XmmRegister, XmmRegister); |
| 434 typedef void (AssemblerX86::*EmitXmmAddr)(XmmRegister, const Address &); | 436 typedef void (AssemblerX8632::*EmitXmmAddr)(XmmRegister, const Address &); |
| 435 typedef void (AssemblerX86::*EmitAddrXmm)(const Address &, XmmRegister); | 437 typedef void (AssemblerX8632::*EmitAddrXmm)(const Address &, XmmRegister); |
| 436 struct XmmEmitterMovOps { | 438 struct XmmEmitterMovOps { |
| 437 EmitXmmXmm XmmXmm; | 439 EmitXmmXmm XmmXmm; |
| 438 EmitXmmAddr XmmAddr; | 440 EmitXmmAddr XmmAddr; |
| 439 EmitAddrXmm AddrXmm; | 441 EmitAddrXmm AddrXmm; |
| 440 }; | 442 }; |
| 441 | 443 |
| 442 typedef void (AssemblerX86::*TypedEmitXmmImm)(Type, XmmRegister, | 444 typedef void (AssemblerX8632::*TypedEmitXmmImm)(Type, XmmRegister, |
| 443 const Immediate &); | 445 const Immediate &); |
| 444 | 446 |
| 445 struct XmmEmitterShiftOp { | 447 struct XmmEmitterShiftOp { |
| 446 TypedEmitXmmXmm XmmXmm; | 448 TypedEmitXmmXmm XmmXmm; |
| 447 TypedEmitXmmAddr XmmAddr; | 449 TypedEmitXmmAddr XmmAddr; |
| 448 TypedEmitXmmImm XmmImm; | 450 TypedEmitXmmImm XmmImm; |
| 449 }; | 451 }; |
| 450 | 452 |
| 451 // Cross Xmm/GPR cast instructions. | 453 // Cross Xmm/GPR cast instructions. |
| 452 template <typename DReg_t, typename SReg_t> struct CastEmitterRegOp { | 454 template <typename DReg_t, typename SReg_t> struct CastEmitterRegOp { |
| 453 typedef void (AssemblerX86::*TypedEmitRegs)(Type, DReg_t, SReg_t); | 455 typedef void (AssemblerX8632::*TypedEmitRegs)(Type, DReg_t, SReg_t); |
| 454 typedef void (AssemblerX86::*TypedEmitAddr)(Type, DReg_t, const Address &); | 456 typedef void (AssemblerX8632::*TypedEmitAddr)(Type, DReg_t, |
| 457 const Address &); |
| 455 | 458 |
| 456 TypedEmitRegs RegReg; | 459 TypedEmitRegs RegReg; |
| 457 TypedEmitAddr RegAddr; | 460 TypedEmitAddr RegAddr; |
| 458 }; | 461 }; |
| 459 | 462 |
| 460 // Three operand (potentially) cross Xmm/GPR instructions. | 463 // Three operand (potentially) cross Xmm/GPR instructions. |
| 461 // The last operand must be an immediate. | 464 // The last operand must be an immediate. |
| 462 template <typename DReg_t, typename SReg_t> struct ThreeOpImmEmitter { | 465 template <typename DReg_t, typename SReg_t> struct ThreeOpImmEmitter { |
| 463 typedef void (AssemblerX86::*TypedEmitRegRegImm)(Type, DReg_t, SReg_t, | 466 typedef void (AssemblerX8632::*TypedEmitRegRegImm)(Type, DReg_t, SReg_t, |
| 464 const Immediate &); | 467 const Immediate &); |
| 465 typedef void (AssemblerX86::*TypedEmitRegAddrImm)(Type, DReg_t, | 468 typedef void (AssemblerX8632::*TypedEmitRegAddrImm)(Type, DReg_t, |
| 466 const Address &, | 469 const Address &, |
| 467 const Immediate &); | 470 const Immediate &); |
| 468 | 471 |
| 469 TypedEmitRegRegImm RegRegImm; | 472 TypedEmitRegRegImm RegRegImm; |
| 470 TypedEmitRegAddrImm RegAddrImm; | 473 TypedEmitRegAddrImm RegAddrImm; |
| 471 }; | 474 }; |
| 472 | 475 |
| 473 /* | 476 /* |
| 474 * Emit Machine Instructions. | 477 * Emit Machine Instructions. |
| 475 */ | 478 */ |
| 476 void call(GPRRegister reg); | 479 void call(GPRRegister reg); |
| 477 void call(const Address &address); | 480 void call(const Address &address); |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 | 849 |
| 847 typedef std::vector<Label *> LabelVector; | 850 typedef std::vector<Label *> LabelVector; |
| 848 // A vector of pool-allocated x86 labels for CFG nodes. | 851 // A vector of pool-allocated x86 labels for CFG nodes. |
| 849 LabelVector CfgNodeLabels; | 852 LabelVector CfgNodeLabels; |
| 850 // A vector of pool-allocated x86 labels for Local labels. | 853 // A vector of pool-allocated x86 labels for Local labels. |
| 851 LabelVector LocalLabels; | 854 LabelVector LocalLabels; |
| 852 | 855 |
| 853 Label *GetOrCreateLabel(SizeT Number, LabelVector &Labels); | 856 Label *GetOrCreateLabel(SizeT Number, LabelVector &Labels); |
| 854 }; | 857 }; |
| 855 | 858 |
| 856 inline void AssemblerX86::EmitUint8(uint8_t value) { | 859 inline void AssemblerX8632::EmitUint8(uint8_t value) { |
| 857 buffer_.Emit<uint8_t>(value); | 860 buffer_.Emit<uint8_t>(value); |
| 858 } | 861 } |
| 859 | 862 |
| 860 inline void AssemblerX86::EmitInt16(int16_t value) { | 863 inline void AssemblerX8632::EmitInt16(int16_t value) { |
| 861 buffer_.Emit<int16_t>(value); | 864 buffer_.Emit<int16_t>(value); |
| 862 } | 865 } |
| 863 | 866 |
| 864 inline void AssemblerX86::EmitInt32(int32_t value) { | 867 inline void AssemblerX8632::EmitInt32(int32_t value) { |
| 865 buffer_.Emit<int32_t>(value); | 868 buffer_.Emit<int32_t>(value); |
| 866 } | 869 } |
| 867 | 870 |
| 868 inline void AssemblerX86::EmitRegisterOperand(int rm, int reg) { | 871 inline void AssemblerX8632::EmitRegisterOperand(int rm, int reg) { |
| 869 assert(rm >= 0 && rm < 8); | 872 assert(rm >= 0 && rm < 8); |
| 870 buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg); | 873 buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg); |
| 871 } | 874 } |
| 872 | 875 |
| 873 inline void AssemblerX86::EmitXmmRegisterOperand(int rm, XmmRegister reg) { | 876 inline void AssemblerX8632::EmitXmmRegisterOperand(int rm, XmmRegister reg) { |
| 874 EmitRegisterOperand(rm, static_cast<GPRRegister>(reg)); | 877 EmitRegisterOperand(rm, static_cast<GPRRegister>(reg)); |
| 875 } | 878 } |
| 876 | 879 |
| 877 inline void AssemblerX86::EmitFixup(AssemblerFixup *fixup) { | 880 inline void AssemblerX8632::EmitFixup(AssemblerFixup *fixup) { |
| 878 buffer_.EmitFixup(fixup); | 881 buffer_.EmitFixup(fixup); |
| 879 } | 882 } |
| 880 | 883 |
| 881 inline void AssemblerX86::EmitOperandSizeOverride() { EmitUint8(0x66); } | 884 inline void AssemblerX8632::EmitOperandSizeOverride() { EmitUint8(0x66); } |
| 882 | 885 |
| 883 } // end of namespace x86 | 886 } // end of namespace X8632 |
| 884 } // end of namespace Ice | 887 } // end of namespace Ice |
| 885 | 888 |
| 886 #endif // SUBZERO_SRC_ASSEMBLER_IA32_H | 889 #endif // SUBZERO_SRC_ASSEMBLER_IA32_H |
| OLD | NEW |