summaryrefslogtreecommitdiff
path: root/src/cmd/5l/noop.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2013-10-31 18:15:55 +0000
committerRuss Cox <rsc@golang.org>2013-10-31 18:15:55 +0000
commit6f84dd781c1c31eaa81385e20bf20d292a62e64f (patch)
tree4901374dd78e94dd382808146cf8f31e6ae8aefa /src/cmd/5l/noop.c
parentc46a59a5450c27897c1974efa539ef29a890a04b (diff)
downloadgo-6f84dd781c1c31eaa81385e20bf20d292a62e64f.tar.gz
cmd/5l, runtime: fix divide for profiling tracebacks on ARM
Two bugs: 1. The first iteration of the traceback always uses LR when provided, which it is (only) during a profiling signal, but in fact LR is correct only if the stack frame has not been allocated yet. Otherwise an intervening call may have changed LR, and the saved copy in the stack frame should be used. Fix in traceback_arm.c. 2. The division runtime call adds 8 bytes to the stack. In order to keep the traceback routines happy, it must copy the saved LR into the new 0(SP). Change SUB $8, SP into MOVW 0(SP), R11 // r11 is temporary, for use by linker MOVW.W R11, -8(SP) to update SP and 0(SP) atomically, so that the traceback always sees a saved LR at 0(SP). Fixes issue 6681. R=golang-dev, r CC=golang-dev https://codereview.appspot.com/19910044
Diffstat (limited to 'src/cmd/5l/noop.c')
-rw-r--r--src/cmd/5l/noop.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/cmd/5l/noop.c b/src/cmd/5l/noop.c
index fb70599b5..305ed684e 100644
--- a/src/cmd/5l/noop.c
+++ b/src/cmd/5l/noop.c
@@ -472,14 +472,27 @@ noops(void)
p->to.reg = REGSP;
p->spadj = -8;
- /* SUB $8,SP */
- q1->as = ASUB;
- q1->from.type = D_CONST;
- q1->from.offset = 8;
- q1->from.reg = NREG;
+ /* Keep saved LR at 0(SP) after SP change. */
+ /* MOVW 0(SP), REGTMP; MOVW REGTMP, -8!(SP) */
+ /* TODO: Remove SP adjustments; see issue 6699. */
+ q1->as = AMOVW;
+ q1->from.type = D_OREG;
+ q1->from.reg = REGSP;
+ q1->from.offset = 0;
q1->reg = NREG;
q1->to.type = D_REG;
+ q1->to.reg = REGTMP;
+
+ /* SUB $8,SP */
+ q1 = appendp(q1);
+ q1->as = AMOVW;
+ q1->from.type = D_REG;
+ q1->from.reg = REGTMP;
+ q1->reg = NREG;
+ q1->to.type = D_OREG;
q1->to.reg = REGSP;
+ q1->to.offset = -8;
+ q1->scond |= C_WBIT;
q1->spadj = 8;
break;