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);
}
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);
}
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);
}
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);
}
// 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;
offset_ = offset;
}
- uint32_t offset() {
+ uint32_t offset() const {
ASSERT(rm_.is(no_reg));
return offset_;
}
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
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,