arm bug with stack adjust

R=r
CC=golang-dev
https://golang.org/cl/3980043
diff --git a/src/cmd/5g/opt.h b/src/cmd/5g/opt.h
index a3e3abc..7a0070f 100644
--- a/src/cmd/5g/opt.h
+++ b/src/cmd/5g/opt.h
@@ -69,7 +69,6 @@
 
 	uint16	loop;		// x5 for every loop
 	uchar	refset;		// diagnostic generated
-	uchar	nomove;		// funny mov instruction
 
 	Reg*	p1;
 	Reg*	p2;
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index a6d35f9..d30d03b 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -143,7 +143,7 @@
 	first++;
 
 	if(debug['K']) {
-		if(first != 4)
+		if(first != 1)
 			return;
 //		debug['R'] = 2;
 //		debug['P'] = 2;
@@ -191,21 +191,6 @@
 		case ANAME:
 		case ASIGNAME:
 			continue;
-
-		case AMOVW:
-			// mark instructions that set SP
-			if(p->to.type == D_REG) {
-				switch(p->to.reg) {
-				case REGSP:
-				case REGLINK:
-				case REGPC:
-					r->nomove = 1;
-					break;
-				}
-			}
-			if(p->scond != C_SCOND_NONE)
-				r->nomove = 1;
-			break;
 		}
 		r = rega();
 		nr++;
@@ -323,6 +308,7 @@
 	if(debug['R']) {
 		p = firstr->prog;
 		print("\n%L %D\n", p->lineno, &p->from);
+		print("	addr = %Q\n", addrs);
 	}
 
 	/*
@@ -386,6 +372,7 @@
 					r->refahead.b[z] | r->calahead.b[z] |
 					r->refbehind.b[z] | r->calbehind.b[z] |
 					r->use1.b[z] | r->use2.b[z];
+				bit.b[z] &= ~addrs.b[z];
 			}
 
 			if(bany(&bit)) {
@@ -511,18 +498,61 @@
 	 * last pass
 	 * eliminate nops
 	 * free aux structures
+	 * adjust the stack pointer
+	 *	MOVW.W 	R1,-12(R13)			<<- start
+	 *	MOVW   	R0,R1
+	 *	MOVW   	R1,8(R13)
+	 *	MOVW   	$0,R1
+	 *	MOVW   	R1,4(R13)
+	 *	BL     	,runtime.newproc+0(SB)
+	 *	MOVW   	&ft+-32(SP),R7			<<- adjust
+	 *	MOVW   	&j+-40(SP),R6			<<- adjust
+	 *	MOVW   	autotmp_0003+-24(SP),R5		<<- adjust
+	 *	MOVW   	$12(R13),R13			<<- finish
 	 */
+	vreg = 0;
 	for(p = firstp; p != P; p = p->link) {
 		while(p->link != P && p->link->as == ANOP)
 			p->link = p->link->link;
 		if(p->to.type == D_BRANCH)
 			while(p->to.branch != P && p->to.branch->as == ANOP)
 				p->to.branch = p->to.branch->link;
+		if(p->as == AMOVW && p->to.reg == 13) {
+			if(p->scond & C_WBIT) {
+				vreg = -p->to.offset;		// in adjust region
+//				print("%P adjusting %d\n", p, vreg);
+				continue;
+			}
+			if(p->from.type == D_CONST && p->to.type == D_REG) {
+				if(p->from.offset != vreg)
+					print("in and out different\n");
+//				print("%P finish %d\n", p, vreg);
+				vreg = 0;	// done adjust region
+				continue;
+			}
+
+//			print("%P %d %d from type\n", p, p->from.type, D_CONST);
+//			print("%P %d %d to type\n\n", p, p->to.type, D_REG);
+		}
+
+		if(p->as == AMOVW && vreg != 0) {
+			if(p->from.sym != S)
+			if(p->from.name == D_AUTO || p->from.name == D_PARAM) {
+				p->from.offset += vreg;
+//				print("%P adjusting from %d %d\n", p, vreg, p->from.type);
+			}
+			if(p->to.sym != S)
+			if(p->to.name == D_AUTO || p->to.name == D_PARAM) {
+				p->to.offset += vreg;
+//				print("%P adjusting to %d %d\n", p, vreg, p->from.type);
+			}
+		}
 	}
 	if(r1 != R) {
 		r1->link = freer;
 		freer = firstr;
 	}
+
 }
 
 void
@@ -1208,12 +1238,6 @@
 		r = r1;
 	}
 
-	// horrible hack to prevent loading a
-	// variable after a call (to defer) but
-	// before popping the SP.
-	if(r->prog->as == ABL && r->nomove)
-		r = r->p1;
-
 	if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
 		addmove(r, bn, rn, 0);