ARM64: Clean up support for explicit literal load.
authorrodolph.perfetta@arm.com <rodolph.perfetta@arm.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 9 Jun 2014 14:23:46 +0000 (14:23 +0000)
committerrodolph.perfetta@arm.com <rodolph.perfetta@arm.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 9 Jun 2014 14:23:46 +0000 (14:23 +0000)
This is the first patch to improve literal pool handling in arm64. Cleans up
assembler/macro-assembler access to literal pools.

BUG=
R=rmcilroy@chromium.org

Review URL: https://codereview.chromium.org/318773009

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21723 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

14 files changed:
src/arm64/assembler-arm64-inl.h
src/arm64/assembler-arm64.cc
src/arm64/assembler-arm64.h
src/arm64/constants-arm64.h
src/arm64/debug-arm64.cc
src/arm64/deoptimizer-arm64.cc
src/arm64/disasm-arm64.cc
src/arm64/full-codegen-arm64.cc
src/arm64/instructions-arm64.cc
src/arm64/instructions-arm64.h
src/arm64/lithium-codegen-arm64.cc
src/arm64/macro-assembler-arm64-inl.h
src/arm64/macro-assembler-arm64.cc
src/arm64/macro-assembler-arm64.h

index 2400f57..135858d 100644 (file)
@@ -261,29 +261,23 @@ inline FPRegister CPURegister::D() const {
 }
 
 
-// Operand.
-template<typename T>
-Operand::Operand(Handle<T> value) : reg_(NoReg) {
-  initialize_handle(value);
-}
-
-
+// Immediate.
 // Default initializer is for int types
-template<typename int_t>
-struct OperandInitializer {
+template<typename T>
+struct ImmediateInitializer {
   static const bool kIsIntType = true;
-  static inline RelocInfo::Mode rmode_for(int_t) {
-    return sizeof(int_t) == 8 ? RelocInfo::NONE64 : RelocInfo::NONE32;
+  static inline RelocInfo::Mode rmode_for(T) {
+    return sizeof(T) == 8 ? RelocInfo::NONE64 : RelocInfo::NONE32;
   }
-  static inline int64_t immediate_for(int_t t) {
-    STATIC_ASSERT(sizeof(int_t) <= 8);
+  static inline int64_t immediate_for(T t) {
+    STATIC_ASSERT(sizeof(T) <= 8);
     return t;
   }
 };
 
 
 template<>
-struct OperandInitializer<Smi*> {
+struct ImmediateInitializer<Smi*> {
   static const bool kIsIntType = false;
   static inline RelocInfo::Mode rmode_for(Smi* t) {
     return RelocInfo::NONE64;
@@ -295,7 +289,7 @@ struct OperandInitializer<Smi*> {
 
 
 template<>
-struct OperandInitializer<ExternalReference> {
+struct ImmediateInitializer<ExternalReference> {
   static const bool kIsIntType = false;
   static inline RelocInfo::Mode rmode_for(ExternalReference t) {
     return RelocInfo::EXTERNAL_REFERENCE;
@@ -307,27 +301,46 @@ struct OperandInitializer<ExternalReference> {
 
 
 template<typename T>
-Operand::Operand(T t)
-    : immediate_(OperandInitializer<T>::immediate_for(t)),
-      reg_(NoReg),
-      rmode_(OperandInitializer<T>::rmode_for(t)) {}
+Immediate::Immediate(Handle<T> value) {
+  InitializeHandle(value);
+}
 
 
 template<typename T>
-Operand::Operand(T t, RelocInfo::Mode rmode)
-    : immediate_(OperandInitializer<T>::immediate_for(t)),
-      reg_(NoReg),
+Immediate::Immediate(T t)
+    : value_(ImmediateInitializer<T>::immediate_for(t)),
+      rmode_(ImmediateInitializer<T>::rmode_for(t)) {}
+
+
+template<typename T>
+Immediate::Immediate(T t, RelocInfo::Mode rmode)
+    : value_(ImmediateInitializer<T>::immediate_for(t)),
       rmode_(rmode) {
-  STATIC_ASSERT(OperandInitializer<T>::kIsIntType);
+  STATIC_ASSERT(ImmediateInitializer<T>::kIsIntType);
 }
 
 
+// Operand.
+template<typename T>
+Operand::Operand(Handle<T> value) : immediate_(value), reg_(NoReg) {}
+
+
+template<typename T>
+Operand::Operand(T t) : immediate_(t), reg_(NoReg) {}
+
+
+template<typename T>
+Operand::Operand(T t, RelocInfo::Mode rmode)
+    : immediate_(t, rmode),
+      reg_(NoReg) {}
+
+
 Operand::Operand(Register reg, Shift shift, unsigned shift_amount)
-    : reg_(reg),
+    : immediate_(0),
+      reg_(reg),
       shift_(shift),
       extend_(NO_EXTEND),
-      shift_amount_(shift_amount),
-      rmode_(reg.Is64Bits() ? RelocInfo::NONE64 : RelocInfo::NONE32) {
+      shift_amount_(shift_amount) {
   ASSERT(reg.Is64Bits() || (shift_amount < kWRegSizeInBits));
   ASSERT(reg.Is32Bits() || (shift_amount < kXRegSizeInBits));
   ASSERT(!reg.IsSP());
@@ -335,11 +348,11 @@ Operand::Operand(Register reg, Shift shift, unsigned shift_amount)
 
 
 Operand::Operand(Register reg, Extend extend, unsigned shift_amount)
-    : reg_(reg),
+    : immediate_(0),
+      reg_(reg),
       shift_(NO_SHIFT),
       extend_(extend),
-      shift_amount_(shift_amount),
-      rmode_(reg.Is64Bits() ? RelocInfo::NONE64 : RelocInfo::NONE32) {
+      shift_amount_(shift_amount) {
   ASSERT(reg.IsValid());
   ASSERT(shift_amount <= 4);
   ASSERT(!reg.IsSP());
@@ -366,7 +379,7 @@ bool Operand::IsExtendedRegister() const {
 
 bool Operand::IsZero() const {
   if (IsImmediate()) {
-    return immediate() == 0;
+    return ImmediateValue() == 0;
   } else {
     return reg().IsZero();
   }
@@ -380,12 +393,18 @@ Operand Operand::ToExtendedRegister() const {
 }
 
 
-int64_t Operand::immediate() const {
+Immediate Operand::immediate() const {
   ASSERT(IsImmediate());
   return immediate_;
 }
 
 
+int64_t Operand::ImmediateValue() const {
+  ASSERT(IsImmediate());
+  return immediate_.value();
+}
+
+
 Register Operand::reg() const {
   ASSERT(IsShiftedRegister() || IsExtendedRegister());
   return reg_;
@@ -473,7 +492,7 @@ MemOperand::MemOperand(Register base, const Operand& offset, AddrMode addrmode)
   ASSERT(base.Is64Bits() && !base.IsZero());
 
   if (offset.IsImmediate()) {
-    offset_ = offset.immediate();
+    offset_ = offset.ImmediateValue();
 
     regoffset_ = NoReg;
   } else if (offset.IsShiftedRegister()) {
@@ -944,6 +963,16 @@ LoadStorePairNonTemporalOp Assembler::StorePairNonTemporalOpFor(
 }
 
 
+LoadLiteralOp Assembler::LoadLiteralOpFor(const CPURegister& rt) {
+  if (rt.IsRegister()) {
+    return rt.Is64Bits() ? LDR_x_lit : LDR_w_lit;
+  } else {
+    ASSERT(rt.IsFPRegister());
+    return rt.Is64Bits() ? LDR_d_lit : LDR_s_lit;
+  }
+}
+
+
 int Assembler::LinkAndGetInstructionOffsetTo(Label* label) {
   ASSERT(kStartOfLabelLinkChain == 0);
   int offset = LinkAndGetByteOffsetTo(label);
@@ -1200,11 +1229,6 @@ const Register& Assembler::AppropriateZeroRegFor(const CPURegister& reg) const {
 }
 
 
-void Assembler::LoadRelocated(const CPURegister& rt, const Operand& operand) {
-  LoadRelocatedValue(rt, operand, LDR_x_lit);
-}
-
-
 inline void Assembler::CheckBufferSpace() {
   ASSERT(pc_ < (buffer_ + buffer_size_));
   if (buffer_space() < kGap) {
index 2654441..90cff59 100644 (file)
@@ -268,29 +268,31 @@ bool AreSameSizeAndType(const CPURegister& reg1, const CPURegister& reg2,
 }
 
 
-void Operand::initialize_handle(Handle<Object> handle) {
+void Immediate::InitializeHandle(Handle<Object> handle) {
   AllowDeferredHandleDereference using_raw_address;
 
   // Verify all Objects referred by code are NOT in new space.
   Object* obj = *handle;
   if (obj->IsHeapObject()) {
     ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
-    immediate_ = reinterpret_cast<intptr_t>(handle.location());
+    value_ = reinterpret_cast<intptr_t>(handle.location());
     rmode_ = RelocInfo::EMBEDDED_OBJECT;
   } else {
     STATIC_ASSERT(sizeof(intptr_t) == sizeof(int64_t));
-    immediate_ = reinterpret_cast<intptr_t>(obj);
+    value_ = reinterpret_cast<intptr_t>(obj);
     rmode_ = RelocInfo::NONE64;
   }
 }
 
 
 bool Operand::NeedsRelocation(const Assembler* assembler) const {
-  if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
+  RelocInfo::Mode rmode = immediate_.rmode();
+
+  if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
     return assembler->serializer_enabled();
   }
 
-  return !RelocInfo::IsNone(rmode_);
+  return !RelocInfo::IsNone(rmode);
 }
 
 
@@ -1473,27 +1475,23 @@ void Assembler::ldrsw(const Register& rt, const MemOperand& src) {
 }
 
 
-void Assembler::ldr(const Register& rt, uint64_t imm) {
-  // TODO(all): Constant pool may be garbage collected. Hence we cannot store
-  // arbitrary values in them. Manually move it for now. Fix
-  // MacroAssembler::Fmov when this is implemented.
-  UNIMPLEMENTED();
+void Assembler::ldr_pcrel(const CPURegister& rt, int imm19) {
+  // The pattern 'ldr xzr, #offset' is used to indicate the beginning of a
+  // constant pool. It should not be emitted.
+  ASSERT(!rt.IsZero());
+  Emit(LoadLiteralOpFor(rt) | ImmLLiteral(imm19) | Rt(rt));
 }
 
 
-void Assembler::ldr(const FPRegister& ft, double imm) {
-  // TODO(all): Constant pool may be garbage collected. Hence we cannot store
-  // arbitrary values in them. Manually move it for now. Fix
-  // MacroAssembler::Fmov when this is implemented.
-  UNIMPLEMENTED();
-}
-
+void Assembler::ldr(const CPURegister& rt, const Immediate& imm) {
+  // Currently we only support 64-bit literals.
+  ASSERT(rt.Is64Bits());
 
-void Assembler::ldr(const FPRegister& ft, float imm) {
-  // TODO(all): Constant pool may be garbage collected. Hence we cannot store
-  // arbitrary values in them. Manually move it for now. Fix
-  // MacroAssembler::Fmov when this is implemented.
-  UNIMPLEMENTED();
+  RecordRelocInfo(imm.rmode(), imm.value());
+  BlockConstPoolFor(1);
+  // The load will be patched when the constpool is emitted, patching code
+  // expect a load literal with offset 0.
+  ldr_pcrel(rt, 0);
 }
 
 
@@ -1919,7 +1917,7 @@ void Assembler::AddSub(const Register& rd,
   ASSERT(rd.SizeInBits() == rn.SizeInBits());
   ASSERT(!operand.NeedsRelocation(this));
   if (operand.IsImmediate()) {
-    int64_t immediate = operand.immediate();
+    int64_t immediate = operand.ImmediateValue();
     ASSERT(IsImmAddSub(immediate));
     Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd);
     Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) |
@@ -2015,7 +2013,7 @@ void Assembler::Logical(const Register& rd,
   ASSERT(rd.SizeInBits() == rn.SizeInBits());
   ASSERT(!operand.NeedsRelocation(this));
   if (operand.IsImmediate()) {
-    int64_t immediate = operand.immediate();
+    int64_t immediate = operand.ImmediateValue();
     unsigned reg_size = rd.SizeInBits();
 
     ASSERT(immediate != 0);
@@ -2067,7 +2065,7 @@ void Assembler::ConditionalCompare(const Register& rn,
   Instr ccmpop;
   ASSERT(!operand.NeedsRelocation(this));
   if (operand.IsImmediate()) {
-    int64_t immediate = operand.immediate();
+    int64_t immediate = operand.ImmediateValue();
     ASSERT(IsImmConditionalCompare(immediate));
     ccmpop = ConditionalCompareImmediateFixed | op | ImmCondCmp(immediate);
   } else {
@@ -2269,28 +2267,6 @@ bool Assembler::IsImmLSScaled(ptrdiff_t offset, LSDataSize size) {
 }
 
 
-void Assembler::LoadLiteral(const CPURegister& rt, int offset_from_pc) {
-  ASSERT((offset_from_pc & ((1 << kLiteralEntrySizeLog2) - 1)) == 0);
-  // The pattern 'ldr xzr, #offset' is used to indicate the beginning of a
-  // constant pool. It should not be emitted.
-  ASSERT(!rt.Is(xzr));
-  Emit(LDR_x_lit |
-       ImmLLiteral(offset_from_pc >> kLiteralEntrySizeLog2) |
-       Rt(rt));
-}
-
-
-void Assembler::LoadRelocatedValue(const CPURegister& rt,
-                                   const Operand& operand,
-                                   LoadLiteralOp op) {
-  int64_t imm = operand.immediate();
-  ASSERT(is_int32(imm) || is_uint32(imm) || (rt.Is64Bits()));
-  RecordRelocInfo(operand.rmode(), imm);
-  BlockConstPoolFor(1);
-  Emit(op | ImmLLiteral(0) | Rt(rt));
-}
-
-
 // Test if a given value can be encoded in the immediate field of a logical
 // instruction.
 // If it can be encoded, the function returns true, and values pointed to by n,
index 8774c09..c0ad4d0 100644 (file)
@@ -599,6 +599,31 @@ class CPURegList {
 #define kCallerSaved CPURegList::GetCallerSaved()
 #define kCallerSavedFP CPURegList::GetCallerSavedFP()
 
+// -----------------------------------------------------------------------------
+// Immediates.
+class Immediate {
+ public:
+  template<typename T>
+  inline explicit Immediate(Handle<T> handle);
+
+  // This is allowed to be an implicit constructor because Immediate is
+  // a wrapper class that doesn't normally perform any type conversion.
+  template<typename T>
+  inline Immediate(T value);  // NOLINT(runtime/explicit)
+
+  template<typename T>
+  inline Immediate(T value, RelocInfo::Mode rmode);
+
+  int64_t value() const { return value_; }
+  RelocInfo::Mode rmode() const { return rmode_; }
+
+ private:
+  void InitializeHandle(Handle<Object> value);
+
+  int64_t value_;
+  RelocInfo::Mode rmode_;
+};
+
 
 // -----------------------------------------------------------------------------
 // Operands.
@@ -634,8 +659,8 @@ class Operand {
   inline Operand(T t);  // NOLINT(runtime/explicit)
 
   // Implicit constructor for int types.
-  template<typename int_t>
-  inline Operand(int_t t, RelocInfo::Mode rmode);
+  template<typename T>
+  inline Operand(T t, RelocInfo::Mode rmode);
 
   inline bool IsImmediate() const;
   inline bool IsShiftedRegister() const;
@@ -646,15 +671,14 @@ class Operand {
   // which helps in the encoding of instructions that use the stack pointer.
   inline Operand ToExtendedRegister() const;
 
-  inline int64_t immediate() const;
+  inline Immediate immediate() const;
+  inline int64_t ImmediateValue() const;
   inline Register reg() const;
   inline Shift shift() const;
   inline Extend extend() const;
   inline unsigned shift_amount() const;
 
   // Relocation information.
-  RelocInfo::Mode rmode() const { return rmode_; }
-  void set_rmode(RelocInfo::Mode rmode) { rmode_ = rmode; }
   bool NeedsRelocation(const Assembler* assembler) const;
 
   // Helpers
@@ -662,13 +686,11 @@ class Operand {
   inline static Operand UntagSmiAndScale(Register smi, int scale);
 
  private:
-  void initialize_handle(Handle<Object> value);
-  int64_t immediate_;
+  Immediate immediate_;
   Register reg_;
   Shift shift_;
   Extend extend_;
   unsigned shift_amount_;
-  RelocInfo::Mode rmode_;
 };
 
 
@@ -1369,9 +1391,6 @@ class Assembler : public AssemblerBase {
 
   // Memory instructions.
 
-  // Load literal from pc + offset_from_pc.
-  void LoadLiteral(const CPURegister& rt, int offset_from_pc);
-
   // Load integer or FP register.
   void ldr(const CPURegister& rt, const MemOperand& src);
 
@@ -1418,12 +1437,11 @@ class Assembler : public AssemblerBase {
   void stnp(const CPURegister& rt, const CPURegister& rt2,
             const MemOperand& dst);
 
-  // Load literal to register.
-  void ldr(const Register& rt, uint64_t imm);
+  // Load literal to register from a pc relative address.
+  void ldr_pcrel(const CPURegister& rt, int imm19);
 
-  // Load literal to FP register.
-  void ldr(const FPRegister& ft, double imm);
-  void ldr(const FPRegister& ft, float imm);
+  // Load literal to register.
+  void ldr(const CPURegister& rt, const Immediate& imm);
 
   // Move instructions. The default shift of -1 indicates that the move
   // instruction will calculate an appropriate 16-bit immediate and left shift
@@ -1841,7 +1859,6 @@ class Assembler : public AssemblerBase {
   void CheckVeneerPool(bool force_emit, bool require_jump,
                        int margin = kVeneerDistanceMargin);
 
-
   class BlockPoolsScope {
    public:
     explicit BlockPoolsScope(Assembler* assem) : assem_(assem) {
@@ -1857,10 +1874,6 @@ class Assembler : public AssemblerBase {
     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope);
   };
 
-  // Available for constrained code generation scopes. Prefer
-  // MacroAssembler::Mov() when possible.
-  inline void LoadRelocated(const CPURegister& rt, const Operand& operand);
-
  protected:
   inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const;
 
@@ -1927,6 +1940,7 @@ class Assembler : public AssemblerBase {
     const CPURegister& rt, const CPURegister& rt2);
   static inline LoadStorePairNonTemporalOp StorePairNonTemporalOpFor(
     const CPURegister& rt, const CPURegister& rt2);
+  static inline LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt);
 
   // Remove the specified branch from the unbound label link chain.
   // If available, a veneer for this label can be used for other branches in the
@@ -1959,11 +1973,6 @@ class Assembler : public AssemblerBase {
                                 const CPURegister& rt2,
                                 const MemOperand& addr,
                                 LoadStorePairNonTemporalOp op);
-  // Register the relocation information for the operand and load its value
-  // into rt.
-  void LoadRelocatedValue(const CPURegister& rt,
-                          const Operand& operand,
-                          LoadLiteralOp op);
   void ConditionalSelect(const Register& rd,
                          const Register& rn,
                          const Register& rm,
index 46852b9..f459b4b 100644 (file)
@@ -25,8 +25,7 @@ namespace internal {
 
 const unsigned kInstructionSize = 4;
 const unsigned kInstructionSizeLog2 = 2;
-const unsigned kLiteralEntrySize = 4;
-const unsigned kLiteralEntrySizeLog2 = 2;
+const unsigned kLoadLiteralScaleLog2 = 2;
 const unsigned kMaxLoadLiteralRange = 1 * MB;
 
 const unsigned kNumberOfRegisters = 32;
index be2d502..5562316 100644 (file)
@@ -46,7 +46,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
 
   // The first instruction of a patched return sequence must be a load literal
   // loading the address of the debug break return code.
-  patcher.LoadLiteral(ip0, 3 * kInstructionSize);
+  patcher.ldr_pcrel(ip0, (3 * kInstructionSize) >> kLoadLiteralScaleLog2);
   // TODO(all): check the following is correct.
   // The debug break return code will push a frame and call statically compiled
   // code. By using blr, even though control will not return after the branch,
@@ -105,7 +105,7 @@ void BreakLocationIterator::SetDebugBreakAtSlot() {
 
   // The first instruction of a patched debug break slot must be a load literal
   // loading the address of the debug break slot code.
-  patcher.LoadLiteral(ip0, 2 * kInstructionSize);
+  patcher.ldr_pcrel(ip0, (2 * kInstructionSize) >> kLoadLiteralScaleLog2);
   // TODO(all): check the following is correct.
   // The debug break slot code will push a frame and call statically compiled
   // code. By using blr, event hough control will not return after the branch,
index f7e43bb..7ac5bd0 100644 (file)
@@ -48,7 +48,7 @@ void Deoptimizer::PatchCodeForDeoptimization(Isolate* isolate, Code* code) {
     Address deopt_entry = GetDeoptimizationEntry(isolate, i, LAZY);
 
     PatchingAssembler patcher(call_address, patch_size() / kInstructionSize);
-    patcher.LoadLiteral(ip0, 2 * kInstructionSize);
+    patcher.ldr_pcrel(ip0, (2 * kInstructionSize) >> kLoadLiteralScaleLog2);
     patcher.blr(ip0);
     patcher.dc64(reinterpret_cast<intptr_t>(deopt_entry));
 
index 614ac39..82e410d 100644 (file)
@@ -1384,7 +1384,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
       switch (format[2]) {
         case 'L': {  // ILLiteral - Immediate Load Literal.
           AppendToOutput("pc%+" PRId64,
-                         instr->ImmLLiteral() << kLiteralEntrySizeLog2);
+                         instr->ImmLLiteral() << kLoadLiteralScaleLog2);
           return 9;
         }
         case 'S': {  // ILS - Immediate Load/Store.
index 2a9b9f1..ba3b5d0 100644 (file)
@@ -459,7 +459,7 @@ void FullCodeGenerator::EmitReturnSequence() {
       // TODO(all): This implementation is overkill as it supports 2**31+1
       // arguments, consider how to improve it without creating a security
       // hole.
-      __ LoadLiteral(ip0, 3 * kInstructionSize);
+      __ ldr_pcrel(ip0, (3 * kInstructionSize) >> kLoadLiteralScaleLog2);
       __ add(current_sp, current_sp, ip0);
       __ ret();
       __ dc64(kXRegSize * (info_->scope()->num_parameters() + 1));
index 3264370..c7334ed 100644 (file)
@@ -280,7 +280,7 @@ void Instruction::SetBranchImmTarget(Instruction* target) {
 
 void Instruction::SetImmLLiteral(Instruction* source) {
   ASSERT(IsAligned(DistanceTo(source), kInstructionSize));
-  ptrdiff_t offset = DistanceTo(source) >> kLiteralEntrySizeLog2;
+  ptrdiff_t offset = DistanceTo(source) >> kLoadLiteralScaleLog2;
   Instr imm = Assembler::ImmLLiteral(offset);
   Instr mask = ImmLLiteral_mask;
 
index a293083..b3d9b79 100644 (file)
@@ -353,7 +353,7 @@ class Instruction {
   void SetImmLLiteral(Instruction* source);
 
   uint8_t* LiteralAddress() {
-    int offset = ImmLLiteral() << kLiteralEntrySizeLog2;
+    int offset = ImmLLiteral() << kLoadLiteralScaleLog2;
     return reinterpret_cast<uint8_t*>(this) + offset;
   }
 
index 60d266a..1ac579f 100644 (file)
@@ -3103,7 +3103,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
     __ bind(&map_check);
     // Will be patched with the cached map.
     Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value());
-    __ LoadRelocated(scratch, Operand(Handle<Object>(cell)));
+    __ ldr(scratch, Immediate(Handle<Object>(cell)));
     __ ldr(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset));
     __ cmp(map, scratch);
     __ b(&cache_miss, ne);
@@ -3111,7 +3111,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
     // above, so check the size of the code generated.
     ASSERT(masm()->InstructionsGeneratedSince(&map_check) == 4);
     // Will be patched with the cached result.
-    __ LoadRelocated(result, Operand(factory()->the_hole_value()));
+    __ ldr(result, Immediate(factory()->the_hole_value()));
   }
   __ B(&done);
 
index 0f8a18d..0c6aadf 100644 (file)
@@ -126,8 +126,8 @@ void MacroAssembler::Ccmp(const Register& rn,
                           StatusFlags nzcv,
                           Condition cond) {
   ASSERT(allow_macro_instructions_);
-  if (operand.IsImmediate() && (operand.immediate() < 0)) {
-    ConditionalCompareMacro(rn, -operand.immediate(), nzcv, cond, CCMN);
+  if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) {
+    ConditionalCompareMacro(rn, -operand.ImmediateValue(), nzcv, cond, CCMN);
   } else {
     ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
   }
@@ -139,8 +139,8 @@ void MacroAssembler::Ccmn(const Register& rn,
                           StatusFlags nzcv,
                           Condition cond) {
   ASSERT(allow_macro_instructions_);
-  if (operand.IsImmediate() && (operand.immediate() < 0)) {
-    ConditionalCompareMacro(rn, -operand.immediate(), nzcv, cond, CCMP);
+  if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) {
+    ConditionalCompareMacro(rn, -operand.ImmediateValue(), nzcv, cond, CCMP);
   } else {
     ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
   }
@@ -151,8 +151,8 @@ void MacroAssembler::Add(const Register& rd,
                          const Register& rn,
                          const Operand& operand) {
   ASSERT(allow_macro_instructions_);
-  if (operand.IsImmediate() && (operand.immediate() < 0)) {
-    AddSubMacro(rd, rn, -operand.immediate(), LeaveFlags, SUB);
+  if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) {
+    AddSubMacro(rd, rn, -operand.ImmediateValue(), LeaveFlags, SUB);
   } else {
     AddSubMacro(rd, rn, operand, LeaveFlags, ADD);
   }
@@ -162,8 +162,8 @@ void MacroAssembler::Adds(const Register& rd,
                           const Register& rn,
                           const Operand& operand) {
   ASSERT(allow_macro_instructions_);
-  if (operand.IsImmediate() && (operand.immediate() < 0)) {
-    AddSubMacro(rd, rn, -operand.immediate(), SetFlags, SUB);
+  if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) {
+    AddSubMacro(rd, rn, -operand.ImmediateValue(), SetFlags, SUB);
   } else {
     AddSubMacro(rd, rn, operand, SetFlags, ADD);
   }
@@ -174,8 +174,8 @@ void MacroAssembler::Sub(const Register& rd,
                          const Register& rn,
                          const Operand& operand) {
   ASSERT(allow_macro_instructions_);
-  if (operand.IsImmediate() && (operand.immediate() < 0)) {
-    AddSubMacro(rd, rn, -operand.immediate(), LeaveFlags, ADD);
+  if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) {
+    AddSubMacro(rd, rn, -operand.ImmediateValue(), LeaveFlags, ADD);
   } else {
     AddSubMacro(rd, rn, operand, LeaveFlags, SUB);
   }
@@ -186,8 +186,8 @@ void MacroAssembler::Subs(const Register& rd,
                           const Register& rn,
                           const Operand& operand) {
   ASSERT(allow_macro_instructions_);
-  if (operand.IsImmediate() && (operand.immediate() < 0)) {
-    AddSubMacro(rd, rn, -operand.immediate(), SetFlags, ADD);
+  if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) {
+    AddSubMacro(rd, rn, -operand.ImmediateValue(), SetFlags, ADD);
   } else {
     AddSubMacro(rd, rn, operand, SetFlags, SUB);
   }
@@ -211,7 +211,7 @@ void MacroAssembler::Neg(const Register& rd,
   ASSERT(allow_macro_instructions_);
   ASSERT(!rd.IsZero());
   if (operand.IsImmediate()) {
-    Mov(rd, -operand.immediate());
+    Mov(rd, -operand.ImmediateValue());
   } else {
     Sub(rd, AppropriateZeroRegFor(rd), operand);
   }
@@ -717,11 +717,7 @@ void MacroAssembler::Fmov(FPRegister fd, double imm) {
   } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) {
     fmov(fd, xzr);
   } else {
-    UseScratchRegisterScope temps(this);
-    Register tmp = temps.AcquireX();
-    // TODO(all): Use Assembler::ldr(const FPRegister& ft, double imm).
-    Mov(tmp, double_to_rawbits(imm));
-    Fmov(fd, tmp);
+    Ldr(fd, imm);
   }
 }
 
@@ -880,16 +876,16 @@ void MacroAssembler::Ldpsw(const Register& rt,
 }
 
 
-void MacroAssembler::Ldr(const FPRegister& ft, double imm) {
+void MacroAssembler::Ldr(const CPURegister& rt, const Immediate& imm) {
   ASSERT(allow_macro_instructions_);
-  ldr(ft, imm);
+  ldr(rt, imm);
 }
 
 
-void MacroAssembler::Ldr(const Register& rt, uint64_t imm) {
+void MacroAssembler::Ldr(const CPURegister& rt, double imm) {
   ASSERT(allow_macro_instructions_);
-  ASSERT(!rt.IsZero());
-  ldr(rt, imm);
+  ASSERT(rt.Is64Bits());
+  ldr(rt, Immediate(double_to_rawbits(imm)));
 }
 
 
@@ -1264,7 +1260,7 @@ void MacroAssembler::BumpSystemStackPointer(const Operand& space) {
     InstructionAccurateScope scope(this);
     ASSERT(space.IsImmediate());
     // Align to 16 bytes.
-    uint64_t imm = RoundUp(space.immediate(), 0x10);
+    uint64_t imm = RoundUp(space.ImmediateValue(), 0x10);
     ASSERT(is_uint24(imm));
 
     Register source = StackPointer();
@@ -1633,7 +1629,7 @@ void MacroAssembler::CompareAndBranch(const Register& lhs,
                                       const Operand& rhs,
                                       Condition cond,
                                       Label* label) {
-  if (rhs.IsImmediate() && (rhs.immediate() == 0) &&
+  if (rhs.IsImmediate() && (rhs.ImmediateValue() == 0) &&
       ((cond == eq) || (cond == ne))) {
     if (cond == eq) {
       Cbz(lhs, label);
index e408126..f2e49b4 100644 (file)
@@ -58,11 +58,11 @@ void MacroAssembler::LogicalMacro(const Register& rd,
 
   if (operand.NeedsRelocation(this)) {
     Register temp = temps.AcquireX();
-    LoadRelocated(temp, operand);
+    Ldr(temp, operand.immediate());
     Logical(rd, rn, temp, op);
 
   } else if (operand.IsImmediate()) {
-    int64_t immediate = operand.immediate();
+    int64_t immediate = operand.ImmediateValue();
     unsigned reg_size = rd.SizeInBits();
     ASSERT(rd.Is64Bits() || is_uint32(immediate));
 
@@ -250,11 +250,11 @@ void MacroAssembler::Mov(const Register& rd,
   Register dst = (rd.IsSP()) ? temps.AcquireSameSizeAs(rd) : rd;
 
   if (operand.NeedsRelocation(this)) {
-    LoadRelocated(dst, operand);
+    Ldr(dst, operand.immediate());
 
   } else if (operand.IsImmediate()) {
     // Call the macro assembler for generic immediates.
-    Mov(dst, operand.immediate());
+    Mov(dst, operand.ImmediateValue());
 
   } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) {
     // Emit a shift instruction if moving a shifted register. This operation
@@ -298,12 +298,12 @@ void MacroAssembler::Mvn(const Register& rd, const Operand& operand) {
   ASSERT(allow_macro_instructions_);
 
   if (operand.NeedsRelocation(this)) {
-    LoadRelocated(rd, operand);
+    Ldr(rd, operand.immediate());
     mvn(rd, rd);
 
   } else if (operand.IsImmediate()) {
     // Call the macro assembler for generic immediates.
-    Mov(rd, ~operand.immediate());
+    Mov(rd, ~operand.ImmediateValue());
 
   } else if (operand.IsExtendedRegister()) {
     // Emit two instructions for the extend case. This differs from Mov, as
@@ -355,11 +355,12 @@ void MacroAssembler::ConditionalCompareMacro(const Register& rn,
   if (operand.NeedsRelocation(this)) {
     UseScratchRegisterScope temps(this);
     Register temp = temps.AcquireX();
-    LoadRelocated(temp, operand);
+    Ldr(temp, operand.immediate());
     ConditionalCompareMacro(rn, temp, nzcv, cond, op);
 
   } else if ((operand.IsShiftedRegister() && (operand.shift_amount() == 0)) ||
-      (operand.IsImmediate() && IsImmConditionalCompare(operand.immediate()))) {
+             (operand.IsImmediate() &&
+              IsImmConditionalCompare(operand.ImmediateValue()))) {
     // The immediate can be encoded in the instruction, or the operand is an
     // unshifted register: call the assembler.
     ConditionalCompare(rn, operand, nzcv, cond, op);
@@ -385,7 +386,7 @@ void MacroAssembler::Csel(const Register& rd,
   if (operand.IsImmediate()) {
     // Immediate argument. Handle special cases of 0, 1 and -1 using zero
     // register.
-    int64_t imm = operand.immediate();
+    int64_t imm = operand.ImmediateValue();
     Register zr = AppropriateZeroRegFor(rn);
     if (imm == 0) {
       csel(rd, rn, zr, cond);
@@ -396,7 +397,7 @@ void MacroAssembler::Csel(const Register& rd,
     } else {
       UseScratchRegisterScope temps(this);
       Register temp = temps.AcquireSameSizeAs(rn);
-      Mov(temp, operand.immediate());
+      Mov(temp, imm);
       csel(rd, rn, temp, cond);
     }
   } else if (operand.IsShiftedRegister() && (operand.shift_amount() == 0)) {
@@ -426,10 +427,11 @@ void MacroAssembler::AddSubMacro(const Register& rd,
   if (operand.NeedsRelocation(this)) {
     UseScratchRegisterScope temps(this);
     Register temp = temps.AcquireX();
-    LoadRelocated(temp, operand);
+    Ldr(temp, operand.immediate());
     AddSubMacro(rd, rn, temp, S, op);
-  } else if ((operand.IsImmediate() && !IsImmAddSub(operand.immediate())) ||
-             (rn.IsZero() && !operand.IsShiftedRegister())                ||
+  } else if ((operand.IsImmediate() &&
+              !IsImmAddSub(operand.ImmediateValue()))      ||
+             (rn.IsZero() && !operand.IsShiftedRegister()) ||
              (operand.IsShiftedRegister() && (operand.shift() == ROR))) {
     UseScratchRegisterScope temps(this);
     Register temp = temps.AcquireSameSizeAs(rn);
@@ -451,7 +453,7 @@ void MacroAssembler::AddSubWithCarryMacro(const Register& rd,
 
   if (operand.NeedsRelocation(this)) {
     Register temp = temps.AcquireX();
-    LoadRelocated(temp, operand);
+    Ldr(temp, operand.immediate());
     AddSubWithCarryMacro(rd, rn, temp, S, op);
 
   } else if (operand.IsImmediate() ||
@@ -1071,7 +1073,7 @@ void MacroAssembler::PushPreamble(Operand total_size) {
     // on entry and the total size of the specified registers must also be a
     // multiple of 16 bytes.
     if (total_size.IsImmediate()) {
-      ASSERT((total_size.immediate() % 16) == 0);
+      ASSERT((total_size.ImmediateValue() % 16) == 0);
     }
 
     // Don't check access size for non-immediate sizes. It's difficult to do
@@ -1091,7 +1093,7 @@ void MacroAssembler::PopPostamble(Operand total_size) {
     // on entry and the total size of the specified registers must also be a
     // multiple of 16 bytes.
     if (total_size.IsImmediate()) {
-      ASSERT((total_size.immediate() % 16) == 0);
+      ASSERT((total_size.ImmediateValue() % 16) == 0);
     }
 
     // Don't check access size for non-immediate sizes. It's difficult to do
@@ -1107,7 +1109,7 @@ void MacroAssembler::PopPostamble(Operand total_size) {
 
 void MacroAssembler::Poke(const CPURegister& src, const Operand& offset) {
   if (offset.IsImmediate()) {
-    ASSERT(offset.immediate() >= 0);
+    ASSERT(offset.ImmediateValue() >= 0);
   } else if (emit_debug_code()) {
     Cmp(xzr, offset);
     Check(le, kStackAccessBelowStackPointer);
@@ -1119,7 +1121,7 @@ void MacroAssembler::Poke(const CPURegister& src, const Operand& offset) {
 
 void MacroAssembler::Peek(const CPURegister& dst, const Operand& offset) {
   if (offset.IsImmediate()) {
-    ASSERT(offset.immediate() >= 0);
+    ASSERT(offset.ImmediateValue() >= 0);
   } else if (emit_debug_code()) {
     Cmp(xzr, offset);
     Check(le, kStackAccessBelowStackPointer);
@@ -2069,7 +2071,7 @@ void MacroAssembler::Call(Address target, RelocInfo::Mode rmode) {
     movk(temp, (imm >> 16) & 0xffff, 16);
     movk(temp, (imm >> 32) & 0xffff, 32);
   } else {
-    LoadRelocated(temp, Operand(reinterpret_cast<intptr_t>(target), rmode));
+    Ldr(temp, Immediate(reinterpret_cast<intptr_t>(target), rmode));
   }
   Blr(temp);
 #ifdef DEBUG
@@ -5173,7 +5175,7 @@ void MacroAssembler::EmitCodeAgeSequence(Assembler * assm,
   //
   // A branch (br) is used rather than a call (blr) because this code replaces
   // the frame setup code that would normally preserve lr.
-  __ LoadLiteral(ip0, kCodeAgeStubEntryOffset);
+  __ ldr_pcrel(ip0, kCodeAgeStubEntryOffset >> kLoadLiteralScaleLog2);
   __ adr(x0, &start);
   __ br(ip0);
   // IsCodeAgeSequence in codegen-arm64.cc assumes that the code generated up
index 3737692..34182c0 100644 (file)
@@ -394,13 +394,10 @@ class MacroAssembler : public Assembler {
   inline void Ldpsw(const Register& rt,
                     const Register& rt2,
                     const MemOperand& src);
-  // Provide both double and float interfaces for FP immediate loads, rather
-  // than relying on implicit C++ casts. This allows signalling NaNs to be
-  // preserved when the immediate matches the format of fd. Most systems convert
-  // signalling NaNs to quiet NaNs when converting between float and double.
-  inline void Ldr(const FPRegister& ft, double imm);
-  inline void Ldr(const FPRegister& ft, float imm);
-  inline void Ldr(const Register& rt, uint64_t imm);
+  // Load a literal from the inline constant pool.
+  inline void Ldr(const CPURegister& rt, const Immediate& imm);
+  // Helper function for double immediate.
+  inline void Ldr(const CPURegister& rt, double imm);
   inline void Lsl(const Register& rd, const Register& rn, unsigned shift);
   inline void Lsl(const Register& rd, const Register& rn, const Register& rm);
   inline void Lsr(const Register& rd, const Register& rn, unsigned shift);