Commit f20d6461 authored by jacob.bramley's avatar jacob.bramley Committed by Commit bot

[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}
parent 1d03fc17
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment