[arm] Fix a double-register push operation.
It is not safe to access memory below sp, and this is also forbidden by the ABI. When pushing, we must either use an atomic operation (such as vstm+db_w) or move sp before writing the data. This patch fixes one stack access, and also adds vpush and vpop helpers to simplify similar code. BUG= Review URL: https://codereview.chromium.org/1378563002 Cr-Commit-Position: refs/heads/master@{#31008}
This commit is contained in:
parent
1d03fc17b4
commit
f20d646152
@ -302,6 +302,13 @@ MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
|
||||
rm_ = no_reg;
|
||||
offset_ = offset;
|
||||
am_ = am;
|
||||
|
||||
// Accesses below the stack pointer are not safe, and are prohibited by the
|
||||
// ABI. We can check obvious violations here.
|
||||
if (rn.is(sp)) {
|
||||
if (am == Offset) DCHECK_LE(0, offset);
|
||||
if (am == NegOffset) DCHECK_GE(0, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1302,6 +1302,14 @@ class Assembler : public AssemblerBase {
|
||||
add(sp, sp, Operand(kPointerSize));
|
||||
}
|
||||
|
||||
void vpush(DwVfpRegister src, Condition cond = al) {
|
||||
vstm(db_w, sp, src, src, cond);
|
||||
}
|
||||
|
||||
void vpop(DwVfpRegister dst, Condition cond = al) {
|
||||
vldm(ia_w, sp, dst, dst, cond);
|
||||
}
|
||||
|
||||
// Jump unconditionally to given label.
|
||||
void jmp(Label* L) { b(L, al); }
|
||||
|
||||
|
@ -278,10 +278,10 @@ void LGapResolver::EmitMove(int index) {
|
||||
MemOperand destination_operand = cgen_->ToMemOperand(destination);
|
||||
if (in_cycle_) {
|
||||
// kScratchDoubleReg was used to break the cycle.
|
||||
__ vstm(db_w, sp, kScratchDoubleReg, kScratchDoubleReg);
|
||||
__ vpush(kScratchDoubleReg);
|
||||
__ vldr(kScratchDoubleReg, source_operand);
|
||||
__ vstr(kScratchDoubleReg, destination_operand);
|
||||
__ vldm(ia_w, sp, kScratchDoubleReg, kScratchDoubleReg);
|
||||
__ vpop(kScratchDoubleReg);
|
||||
} else {
|
||||
__ vldr(kScratchDoubleReg, source_operand);
|
||||
__ vstr(kScratchDoubleReg, destination_operand);
|
||||
|
@ -831,10 +831,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
}
|
||||
case kArmPush:
|
||||
if (instr->InputAt(0)->IsDoubleRegister()) {
|
||||
__ vstr(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize));
|
||||
__ sub(sp, sp, Operand(kDoubleSize));
|
||||
__ vpush(i.InputDoubleRegister(0));
|
||||
} else {
|
||||
__ Push(i.InputRegister(0));
|
||||
__ push(i.InputRegister(0));
|
||||
}
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user