From: whesse@chromium.org Date: Thu, 17 Feb 2011 10:07:13 +0000 (+0000) Subject: ARM: Enable loads and stores of VFP registers with offsets >= 1024 bytes. X-Git-Tag: upstream/4.7.83~20176 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=26421683317dd8083f9eed10a14524975ee02076;p=platform%2Fupstream%2Fv8.git ARM: Enable loads and stores of VFP registers with offsets >= 1024 bytes. Review URL: http://codereview.chromium.org/6530002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6830 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc index fb9bb48..8441cae 100644 --- a/src/arm/assembler-arm.cc +++ b/src/arm/assembler-arm.cc @@ -1848,11 +1848,31 @@ void Assembler::vldr(const DwVfpRegister dst, offset = -offset; u = 0; } - ASSERT(offset % 4 == 0); - ASSERT((offset / 4) < 256); + ASSERT(offset >= 0); - emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 | - 0xB*B8 | ((offset / 4) & 255)); + if ((offset % 4) == 0 && (offset / 4) < 256) { + emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 | + 0xB*B8 | ((offset / 4) & 255)); + } else { + // Larger offsets must be handled by computing the correct address + // in the ip register. + ASSERT(!base.is(ip)); + if (u == 1) { + add(ip, base, Operand(offset)); + } else { + sub(ip, base, Operand(offset)); + } + emit(cond | 0xD1*B20 | ip.code()*B16 | dst.code()*B12 | 0xB*B8); + } +} + + +void Assembler::vldr(const DwVfpRegister dst, + const MemOperand& operand, + const Condition cond) { + ASSERT(!operand.rm().is_valid()); + ASSERT(operand.am_ == Offset); + vldr(dst, operand.rn(), operand.offset(), cond); } @@ -1870,13 +1890,33 @@ void Assembler::vldr(const SwVfpRegister dst, offset = -offset; u = 0; } - ASSERT(offset % 4 == 0); - ASSERT((offset / 4) < 256); - ASSERT(offset >= 0); int sd, d; dst.split_code(&sd, &d); + ASSERT(offset >= 0); + + if ((offset % 4) == 0 && (offset / 4) < 256) { emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 | 0xA*B8 | ((offset / 4) & 255)); + } else { + // Larger offsets must be handled by computing the correct address + // in the ip register. + ASSERT(!base.is(ip)); + if (u == 1) { + add(ip, base, Operand(offset)); + } else { + sub(ip, base, Operand(offset)); + } + emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8); + } +} + + +void Assembler::vldr(const SwVfpRegister dst, + const MemOperand& operand, + const Condition cond) { + ASSERT(!operand.rm().is_valid()); + ASSERT(operand.am_ == Offset); + vldr(dst, operand.rn(), operand.offset(), cond); } @@ -1894,11 +1934,30 @@ void Assembler::vstr(const DwVfpRegister src, offset = -offset; u = 0; } - ASSERT(offset % 4 == 0); - ASSERT((offset / 4) < 256); ASSERT(offset >= 0); - emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 | - 0xB*B8 | ((offset / 4) & 255)); + if ((offset % 4) == 0 && (offset / 4) < 256) { + emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 | + 0xB*B8 | ((offset / 4) & 255)); + } else { + // Larger offsets must be handled by computing the correct address + // in the ip register. + ASSERT(!base.is(ip)); + if (u == 1) { + add(ip, base, Operand(offset)); + } else { + sub(ip, base, Operand(offset)); + } + emit(cond | 0xD0*B20 | ip.code()*B16 | src.code()*B12 | 0xB*B8); + } +} + + +void Assembler::vstr(const DwVfpRegister src, + const MemOperand& operand, + const Condition cond) { + ASSERT(!operand.rm().is_valid()); + ASSERT(operand.am_ == Offset); + vldr(src, operand.rn(), operand.offset(), cond); } @@ -1916,13 +1975,32 @@ void Assembler::vstr(const SwVfpRegister src, offset = -offset; u = 0; } - ASSERT(offset % 4 == 0); - ASSERT((offset / 4) < 256); - ASSERT(offset >= 0); int sd, d; src.split_code(&sd, &d); - emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 | - 0xA*B8 | ((offset / 4) & 255)); + ASSERT(offset >= 0); + if ((offset % 4) == 0 && (offset / 4) < 256) { + emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 | + 0xA*B8 | ((offset / 4) & 255)); + } else { + // Larger offsets must be handled by computing the correct address + // in the ip register. + ASSERT(!base.is(ip)); + if (u == 1) { + add(ip, base, Operand(offset)); + } else { + sub(ip, base, Operand(offset)); + } + emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8); + } +} + + +void Assembler::vstr(const SwVfpRegister src, + const MemOperand& operand, + const Condition cond) { + ASSERT(!operand.rm().is_valid()); + ASSERT(operand.am_ == Offset); + vldr(src, operand.rn(), operand.offset(), cond); } diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h index 3941c84..954b9cf 100644 --- a/src/arm/assembler-arm.h +++ b/src/arm/assembler-arm.h @@ -387,7 +387,7 @@ class Operand BASE_EMBEDDED { // Return true if this is a register operand. INLINE(bool is_reg() const); - // Return true of this operand fits in one instruction so that no + // Return true if this operand fits in one instruction so that no // 2-instruction solution with a load into the ip register is necessary. bool is_single_instruction() const; bool must_use_constant_pool() const; @@ -439,7 +439,7 @@ class MemOperand BASE_EMBEDDED { offset_ = offset; } - uint32_t offset() { + uint32_t offset() const { ASSERT(rm_.is(no_reg)); return offset_; } @@ -447,6 +447,10 @@ class MemOperand BASE_EMBEDDED { Register rn() const { return rn_; } Register rm() const { return rm_; } + bool OffsetIsUint12Encodable() const { + return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_); + } + private: Register rn_; // base Register rm_; // register offset @@ -902,22 +906,34 @@ class Assembler : public Malloced { void vldr(const DwVfpRegister dst, const Register base, - int offset, // Offset must be a multiple of 4. + int offset, + const Condition cond = al); + void vldr(const DwVfpRegister dst, + const MemOperand& src, const Condition cond = al); void vldr(const SwVfpRegister dst, const Register base, - int offset, // Offset must be a multiple of 4. + int offset, + const Condition cond = al); + void vldr(const SwVfpRegister dst, + const MemOperand& src, const Condition cond = al); void vstr(const DwVfpRegister src, const Register base, - int offset, // Offset must be a multiple of 4. + int offset, + const Condition cond = al); + void vstr(const DwVfpRegister src, + const MemOperand& dst, const Condition cond = al); void vstr(const SwVfpRegister src, const Register base, - int offset, // Offset must be a multiple of 4. + int offset, + const Condition cond = al); + void vstr(const SwVfpRegister src, + const MemOperand& dst, const Condition cond = al); void vmov(const DwVfpRegister dst,