arm: bugfixes and syscall

- integer divide by zero raises panic
- float comparisons involving NaNs work
- syscall interface actually handles return
  values and errno correctly.

R=rsc, bradfitzpatrick
CC=golang-dev
https://golang.org/cl/1847047
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index b0c9b88..310ea99 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -1044,7 +1044,16 @@
 		cgen(nr, &n2);
 
 		gcmp(optoas(OCMP, nr->type), &n1, &n2);
-		patch(gbranch(a, nr->type), to);
+		if(isfloat[nl->type->etype]) {
+			p1 = gbranch(ABVS, nr->type);
+			patch(gbranch(a, nr->type), to);
+			if(n->op == ONE)
+				patch(p1, to);
+			else
+				patch(p1, pc);
+		} else {
+			patch(gbranch(a, nr->type), to);
+		}
 
 		regfree(&n1);
 		regfree(&n2);
diff --git a/src/pkg/runtime/arm/vlop.s b/src/pkg/runtime/arm/vlop.s
index c9e7090..f95f0f1 100644
--- a/src/pkg/runtime/arm/vlop.s
+++ b/src/pkg/runtime/arm/vlop.s
@@ -62,7 +62,7 @@
 	MOVW	20(FP), R(D)		/* denominator */
 	CMP	$0, R(D)
 	BNE	s1
-	SWI		 0
+	BL	panicdivide(SB)
 /*	  MOVW	-1(R(D)), R(TMP)	/* divide by zero fault */
 s1:	 RET
 
diff --git a/src/pkg/runtime/arm/vlrt.c b/src/pkg/runtime/arm/vlrt.c
index 76b777a..51ae15b 100644
--- a/src/pkg/runtime/arm/vlrt.c
+++ b/src/pkg/runtime/arm/vlrt.c
@@ -23,6 +23,9 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
+// declared here to avoid include of runtime.h
+void	panicstring(char*);
+
 typedef unsigned long   ulong;
 typedef unsigned int    uint;
 typedef unsigned short  ushort;
@@ -31,6 +34,12 @@
 
 #define SIGN(n) (1UL<<(n-1))
 
+void
+panicdivide(void)
+{
+	panicstring("integer divide by zero");
+}
+
 typedef struct  Vlong   Vlong;
 struct  Vlong
 {
@@ -47,8 +56,8 @@
 			ushort loms;
 			ushort hils;
 			ushort hims;
-                };
-        };
+		};
+	};
 };
 
 void    abort(void);
@@ -56,90 +65,90 @@
 void
 _addv(Vlong *r, Vlong a, Vlong b)
 {
-        ulong lo, hi;
+	ulong lo, hi;
 
-        lo = a.lo + b.lo;
-        hi = a.hi + b.hi;
-        if(lo < a.lo)
-                hi++;
-        r->lo = lo;
-        r->hi = hi;
+	lo = a.lo + b.lo;
+	hi = a.hi + b.hi;
+	if(lo < a.lo)
+		hi++;
+	r->lo = lo;
+	r->hi = hi;
 }
 
 void
 _subv(Vlong *r, Vlong a, Vlong b)
 {
-        ulong lo, hi;
+	ulong lo, hi;
 
-        lo = a.lo - b.lo;
-        hi = a.hi - b.hi;
-        if(lo > a.lo)
-                hi--;
-        r->lo = lo;
-        r->hi = hi;
+	lo = a.lo - b.lo;
+	hi = a.hi - b.hi;
+	if(lo > a.lo)
+		hi--;
+	r->lo = lo;
+	r->hi = hi;
 }
 
 
 void
 _d2v(Vlong *y, double d)
 {
-        union { double d; struct Vlong; } x;
-        ulong xhi, xlo, ylo, yhi;
-        int sh;
+	union { double d; struct Vlong; } x;
+	ulong xhi, xlo, ylo, yhi;
+	int sh;
 
-        x.d = d;
+	x.d = d;
 
-        xhi = (x.hi & 0xfffff) | 0x100000;
-        xlo = x.lo;
-        sh = 1075 - ((x.hi >> 20) & 0x7ff);
+	xhi = (x.hi & 0xfffff) | 0x100000;
+	xlo = x.lo;
+	sh = 1075 - ((x.hi >> 20) & 0x7ff);
 
-        ylo = 0;
-        yhi = 0;
-        if(sh >= 0) {
-                /* v = (hi||lo) >> sh */
-                if(sh < 32) {
-                        if(sh == 0) {
-                                ylo = xlo;
-                                yhi = xhi;
-                        } else {
-                                ylo = (xlo >> sh) | (xhi << (32-sh));
-                                yhi = xhi >> sh;
-                        }
-                } else {
-                        if(sh == 32) {
-                                ylo = xhi;
-                        } else
-                        if(sh < 64) {
-                                ylo = xhi >> (sh-32);
-                        }
-                }
-        } else {
-                /* v = (hi||lo) << -sh */
-                sh = -sh;
-                if(sh <= 10) {
-                        ylo = xlo << sh;
-                        yhi = (xhi << sh) | (xlo >> (32-sh));
-                } else {
-                        /* overflow */
-                        yhi = d;        /* causes something awful */
-                }
-        }
-        if(x.hi & SIGN(32)) {
-                if(ylo != 0) {
-                        ylo = -ylo;
-                        yhi = ~yhi;
-                } else
-                        yhi = -yhi;
-        }
+	ylo = 0;
+	yhi = 0;
+	if(sh >= 0) {
+		/* v = (hi||lo) >> sh */
+		if(sh < 32) {
+			if(sh == 0) {
+				ylo = xlo;
+				yhi = xhi;
+			} else {
+				ylo = (xlo >> sh) | (xhi << (32-sh));
+				yhi = xhi >> sh;
+			}
+		} else {
+			if(sh == 32) {
+				ylo = xhi;
+			} else
+			if(sh < 64) {
+				ylo = xhi >> (sh-32);
+			}
+		}
+	} else {
+		/* v = (hi||lo) << -sh */
+		sh = -sh;
+		if(sh <= 10) {
+			ylo = xlo << sh;
+			yhi = (xhi << sh) | (xlo >> (32-sh));
+		} else {
+			/* overflow */
+			yhi = d;        /* causes something awful */
+		}
+	}
+	if(x.hi & SIGN(32)) {
+		if(ylo != 0) {
+			ylo = -ylo;
+			yhi = ~yhi;
+		} else
+			yhi = -yhi;
+	}
 
-        y->hi = yhi;
-        y->lo = ylo;
+	y->hi = yhi;
+	y->lo = ylo;
 }
 
 void
 _f2v(Vlong *y, float f)
 {
-        _d2v(y, f);
+	_d2v(y, f);
 }
 
 void
@@ -151,21 +160,21 @@
 double
 _v2d(Vlong x)
 {
-        if(x.hi & SIGN(32)) {
-                if(x.lo) {
-                        x.lo = -x.lo;
-                        x.hi = ~x.hi;
-                } else
-                        x.hi = -x.hi;
-                return -((long)x.hi*4294967296. + x.lo);
-        }
-        return (long)x.hi*4294967296. + x.lo;
+	if(x.hi & SIGN(32)) {
+		if(x.lo) {
+			x.lo = -x.lo;
+			x.hi = ~x.hi;
+		} else
+			x.hi = -x.hi;
+		return -((long)x.hi*4294967296. + x.lo);
+	}
+	return (long)x.hi*4294967296. + x.lo;
 }
 
 float
 _v2f(Vlong x)
 {
-        return _v2d(x);
+	return _v2d(x);
 }
 
 void
@@ -178,75 +187,75 @@
 static void
 dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
 {
-        ulong numlo, numhi, denhi, denlo, quohi, quolo, t;
-        int i;
+	ulong numlo, numhi, denhi, denlo, quohi, quolo, t;
+	int i;
 
-        numhi = num.hi;
-        numlo = num.lo;
-        denhi = den.hi;
-        denlo = den.lo;
+	numhi = num.hi;
+	numlo = num.lo;
+	denhi = den.hi;
+	denlo = den.lo;
 
-        /*
-         * get a divide by zero
-         */
-        if(denlo==0 && denhi==0) {
-                numlo = numlo / denlo;
-        }
+	/*
+	 * get a divide by zero
+	 */
+	if(denlo==0 && denhi==0) {
+		panicdivide();
+	}
 
-        /*
-         * set up the divisor and find the number of iterations needed
-         */
-        if(numhi >= SIGN(32)) {
-                quohi = SIGN(32);
-                quolo = 0;
-        } else {
-                quohi = numhi;
-                quolo = numlo;
-        }
-        i = 0;
-        while(denhi < quohi || (denhi == quohi && denlo < quolo)) {
-                denhi = (denhi<<1) | (denlo>>31);
-                denlo <<= 1;
-                i++;
-        }
+	/*
+	 * set up the divisor and find the number of iterations needed
+	 */
+	if(numhi >= SIGN(32)) {
+		quohi = SIGN(32);
+		quolo = 0;
+	} else {
+		quohi = numhi;
+		quolo = numlo;
+	}
+	i = 0;
+	while(denhi < quohi || (denhi == quohi && denlo < quolo)) {
+		denhi = (denhi<<1) | (denlo>>31);
+		denlo <<= 1;
+		i++;
+	}
 
-        quohi = 0;
-        quolo = 0;
-        for(; i >= 0; i--) {
-                quohi = (quohi<<1) | (quolo>>31);
-                quolo <<= 1;
-                if(numhi > denhi || (numhi == denhi && numlo >= denlo)) {
-                        t = numlo;
-                        numlo -= denlo;
-                        if(numlo > t)
-                                numhi--;
-                        numhi -= denhi;
-                        quolo |= 1;
-                }
-                denlo = (denlo>>1) | (denhi<<31);
-                denhi >>= 1;
-        }
+	quohi = 0;
+	quolo = 0;
+	for(; i >= 0; i--) {
+		quohi = (quohi<<1) | (quolo>>31);
+		quolo <<= 1;
+		if(numhi > denhi || (numhi == denhi && numlo >= denlo)) {
+			t = numlo;
+			numlo -= denlo;
+			if(numlo > t)
+				numhi--;
+			numhi -= denhi;
+			quolo |= 1;
+		}
+		denlo = (denlo>>1) | (denhi<<31);
+		denhi >>= 1;
+	}
 
-        if(q) {
-                q->lo = quolo;
-                q->hi = quohi;
-        }
-        if(r) {
-                r->lo = numlo;
-                r->hi = numhi;
-        }
+	if(q) {
+		q->lo = quolo;
+		q->hi = quohi;
+	}
+	if(r) {
+		r->lo = numlo;
+		r->hi = numhi;
+	}
 }
 
 void
 _divvu(Vlong *q, Vlong n, Vlong d)
 {
 
-        if(n.hi == 0 && d.hi == 0) {
-                q->hi = 0;
-                q->lo = n.lo / d.lo;
-                return;
-        }
-        dodiv(n, d, q, 0);
+	if(n.hi == 0 && d.hi == 0) {
+		q->hi = 0;
+		q->lo = n.lo / d.lo;
+		return;
+	}
+	dodiv(n, d, q, 0);
 }
 
 void
@@ -259,12 +268,12 @@
 _modvu(Vlong *r, Vlong n, Vlong d)
 {
 
-        if(n.hi == 0 && d.hi == 0) {
-                r->hi = 0;
-                r->lo = n.lo % d.lo;
-                return;
-        }
-        dodiv(n, d, 0, r);
+	if(n.hi == 0 && d.hi == 0) {
+		r->hi = 0;
+		r->lo = n.lo % d.lo;
+		return;
+	}
+	dodiv(n, d, 0, r);
 }
 
 void
@@ -277,20 +286,20 @@
 vneg(Vlong *v)
 {
 
-        if(v->lo == 0) {
-                v->hi = -v->hi;
-                return;
-        }
-        v->lo = -v->lo;
-        v->hi = ~v->hi;
+	if(v->lo == 0) {
+		v->hi = -v->hi;
+		return;
+	}
+	v->lo = -v->lo;
+	v->hi = ~v->hi;
 }
 
 void
 _divv(Vlong *q, Vlong n, Vlong d)
 {
-        long nneg, dneg;
+	long nneg, dneg;
 
-        if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
+	if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
 		if((long)n.lo == -0x80000000 && (long)d.lo == -1) {
 			// special case: 32-bit -0x80000000 / -1 causes wrong sign
 			q->lo = 0x80000000;
@@ -300,16 +309,16 @@
 		q->lo = (long)n.lo / (long)d.lo;
 		q->hi = ((long)q->lo) >> 31;
 		return;
-        }
-        nneg = n.hi >> 31;
-        if(nneg)
-                vneg(&n);
-        dneg = d.hi >> 31;
-        if(dneg)
-                vneg(&d);
-        dodiv(n, d, q, 0);
-        if(nneg != dneg)
-                vneg(q);
+	}
+	nneg = n.hi >> 31;
+	if(nneg)
+		vneg(&n);
+	dneg = d.hi >> 31;
+	if(dneg)
+		vneg(&d);
+	dodiv(n, d, q, 0);
+	if(nneg != dneg)
+		vneg(q);
 }
 
 void
@@ -321,22 +330,22 @@
 void
 _modv(Vlong *r, Vlong n, Vlong d)
 {
-        long nneg, dneg;
+	long nneg, dneg;
 
-        if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
-                r->lo = (long)n.lo % (long)d.lo;
-                r->hi = ((long)r->lo) >> 31;
-                return;
-        }
-        nneg = n.hi >> 31;
-        if(nneg)
-                vneg(&n);
-        dneg = d.hi >> 31;
-        if(dneg)
-                vneg(&d);
-        dodiv(n, d, 0, r);
-        if(nneg)
-                vneg(r);
+	if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
+		r->lo = (long)n.lo % (long)d.lo;
+		r->hi = ((long)r->lo) >> 31;
+		return;
+	}
+	nneg = n.hi >> 31;
+	if(nneg)
+		vneg(&n);
+	dneg = d.hi >> 31;
+	if(dneg)
+		vneg(&d);
+	dodiv(n, d, 0, r);
+	if(nneg)
+		vneg(r);
 }
 
 void
@@ -348,439 +357,439 @@
 void
 _rshav(Vlong *r, Vlong a, int b)
 {
-        long t;
+	long t;
 
-        t = a.hi;
-        if(b >= 32) {
-                r->hi = t>>31;
-                if(b >= 64) {
-                        /* this is illegal re C standard */
-                        r->lo = t>>31;
-                        return;
-                }
-                r->lo = t >> (b-32);
-                return;
-        }
-        if(b <= 0) {
-                r->hi = t;
-                r->lo = a.lo;
-                return;
-        }
-        r->hi = t >> b;
-        r->lo = (t << (32-b)) | (a.lo >> b);
+	t = a.hi;
+	if(b >= 32) {
+		r->hi = t>>31;
+		if(b >= 64) {
+			/* this is illegal re C standard */
+			r->lo = t>>31;
+			return;
+		}
+		r->lo = t >> (b-32);
+		return;
+	}
+	if(b <= 0) {
+		r->hi = t;
+		r->lo = a.lo;
+		return;
+	}
+	r->hi = t >> b;
+	r->lo = (t << (32-b)) | (a.lo >> b);
 }
 
 void
 _rshlv(Vlong *r, Vlong a, int b)
 {
-        ulong t;
+	ulong t;
 
-        t = a.hi;
-        if(b >= 32) {
-                r->hi = 0;
-                if(b >= 64) {
-                        /* this is illegal re C standard */
-                        r->lo = 0;
-                        return;
-                }
-                r->lo = t >> (b-32);
-                return;
-        }
-        if(b <= 0) {
-                r->hi = t;
-                r->lo = a.lo;
-                return;
-        }
-        r->hi = t >> b;
-        r->lo = (t << (32-b)) | (a.lo >> b);
+	t = a.hi;
+	if(b >= 32) {
+		r->hi = 0;
+		if(b >= 64) {
+			/* this is illegal re C standard */
+			r->lo = 0;
+			return;
+		}
+		r->lo = t >> (b-32);
+		return;
+	}
+	if(b <= 0) {
+		r->hi = t;
+		r->lo = a.lo;
+		return;
+	}
+	r->hi = t >> b;
+	r->lo = (t << (32-b)) | (a.lo >> b);
 }
 
 void
 _lshv(Vlong *r, Vlong a, int b)
 {
-        ulong t;
+	ulong t;
 
-        t = a.lo;
-        if(b >= 32) {
-                r->lo = 0;
-                if(b >= 64) {
-                        /* this is illegal re C standard */
-                        r->hi = 0;
-                        return;
-                }
-                r->hi = t << (b-32);
-                return;
-        }
-        if(b <= 0) {
-                r->lo = t;
-                r->hi = a.hi;
-                return;
-        }
-        r->lo = t << b;
-        r->hi = (t >> (32-b)) | (a.hi << b);
+	t = a.lo;
+	if(b >= 32) {
+		r->lo = 0;
+		if(b >= 64) {
+			/* this is illegal re C standard */
+			r->hi = 0;
+			return;
+		}
+		r->hi = t << (b-32);
+		return;
+	}
+	if(b <= 0) {
+		r->lo = t;
+		r->hi = a.hi;
+		return;
+	}
+	r->lo = t << b;
+	r->hi = (t >> (32-b)) | (a.hi << b);
 }
 
 void
 _andv(Vlong *r, Vlong a, Vlong b)
 {
-        r->hi = a.hi & b.hi;
-        r->lo = a.lo & b.lo;
+	r->hi = a.hi & b.hi;
+	r->lo = a.lo & b.lo;
 }
 
 void
 _orv(Vlong *r, Vlong a, Vlong b)
 {
-        r->hi = a.hi | b.hi;
-        r->lo = a.lo | b.lo;
+	r->hi = a.hi | b.hi;
+	r->lo = a.lo | b.lo;
 }
 
 void
 _xorv(Vlong *r, Vlong a, Vlong b)
 {
-        r->hi = a.hi ^ b.hi;
-        r->lo = a.lo ^ b.lo;
+	r->hi = a.hi ^ b.hi;
+	r->lo = a.lo ^ b.lo;
 }
 
 void
 _vpp(Vlong *l, Vlong *r)
 {
 
-        l->hi = r->hi;
-        l->lo = r->lo;
-        r->lo++;
-        if(r->lo == 0)
-                r->hi++;
+	l->hi = r->hi;
+	l->lo = r->lo;
+	r->lo++;
+	if(r->lo == 0)
+		r->hi++;
 }
 
 void
 _vmm(Vlong *l, Vlong *r)
 {
 
-        l->hi = r->hi;
-        l->lo = r->lo;
-        if(r->lo == 0)
-                r->hi--;
-        r->lo--;
+	l->hi = r->hi;
+	l->lo = r->lo;
+	if(r->lo == 0)
+		r->hi--;
+	r->lo--;
 }
 
 void
 _ppv(Vlong *l, Vlong *r)
 {
 
-        r->lo++;
-        if(r->lo == 0)
-                r->hi++;
-        l->hi = r->hi;
-        l->lo = r->lo;
+	r->lo++;
+	if(r->lo == 0)
+		r->hi++;
+	l->hi = r->hi;
+	l->lo = r->lo;
 }
 
 void
 _mmv(Vlong *l, Vlong *r)
 {
 
-        if(r->lo == 0)
-                r->hi--;
-        r->lo--;
-        l->hi = r->hi;
-        l->lo = r->lo;
+	if(r->lo == 0)
+		r->hi--;
+	r->lo--;
+	l->hi = r->hi;
+	l->lo = r->lo;
 }
 
 void
 _vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
 {
-        Vlong t, u;
+	Vlong t, u;
 
-        u = *ret;
-        switch(type) {
-        default:
-                abort();
-                break;
+	u = *ret;
+	switch(type) {
+	default:
+		abort();
+		break;
 
-        case 1: /* schar */
-                t.lo = *(schar*)lv;
-                t.hi = t.lo >> 31;
-                fn(&u, t, rv);
-                *(schar*)lv = u.lo;
-                break;
+	case 1: /* schar */
+		t.lo = *(schar*)lv;
+		t.hi = t.lo >> 31;
+		fn(&u, t, rv);
+		*(schar*)lv = u.lo;
+		break;
 
-        case 2: /* uchar */
-                t.lo = *(uchar*)lv;
-                t.hi = 0;
-                fn(&u, t, rv);
-                *(uchar*)lv = u.lo;
-                break;
+	case 2: /* uchar */
+		t.lo = *(uchar*)lv;
+		t.hi = 0;
+		fn(&u, t, rv);
+		*(uchar*)lv = u.lo;
+		break;
 
-        case 3: /* short */
-                t.lo = *(short*)lv;
-                t.hi = t.lo >> 31;
-                fn(&u, t, rv);
-                *(short*)lv = u.lo;
-                break;
+	case 3: /* short */
+		t.lo = *(short*)lv;
+		t.hi = t.lo >> 31;
+		fn(&u, t, rv);
+		*(short*)lv = u.lo;
+		break;
 
-        case 4: /* ushort */
-                t.lo = *(ushort*)lv;
-                t.hi = 0;
-                fn(&u, t, rv);
-                *(ushort*)lv = u.lo;
-                break;
+	case 4: /* ushort */
+		t.lo = *(ushort*)lv;
+		t.hi = 0;
+		fn(&u, t, rv);
+		*(ushort*)lv = u.lo;
+		break;
 
-        case 9: /* int */
-                t.lo = *(int*)lv;
-                t.hi = t.lo >> 31;
-                fn(&u, t, rv);
-                *(int*)lv = u.lo;
-                break;
+	case 9: /* int */
+		t.lo = *(int*)lv;
+		t.hi = t.lo >> 31;
+		fn(&u, t, rv);
+		*(int*)lv = u.lo;
+		break;
 
-        case 10:        /* uint */
-                t.lo = *(uint*)lv;
-                t.hi = 0;
-                fn(&u, t, rv);
-                *(uint*)lv = u.lo;
-                break;
+	case 10:        /* uint */
+		t.lo = *(uint*)lv;
+		t.hi = 0;
+		fn(&u, t, rv);
+		*(uint*)lv = u.lo;
+		break;
 
-        case 5: /* long */
-                t.lo = *(long*)lv;
-                t.hi = t.lo >> 31;
-                fn(&u, t, rv);
-                *(long*)lv = u.lo;
-                break;
+	case 5: /* long */
+		t.lo = *(long*)lv;
+		t.hi = t.lo >> 31;
+		fn(&u, t, rv);
+		*(long*)lv = u.lo;
+		break;
 
-        case 6: /* ulong */
-                t.lo = *(ulong*)lv;
-                t.hi = 0;
-                fn(&u, t, rv);
-                *(ulong*)lv = u.lo;
-                break;
+	case 6: /* ulong */
+		t.lo = *(ulong*)lv;
+		t.hi = 0;
+		fn(&u, t, rv);
+		*(ulong*)lv = u.lo;
+		break;
 
-        case 7: /* vlong */
-        case 8: /* uvlong */
-                fn(&u, *(Vlong*)lv, rv);
-                *(Vlong*)lv = u;
-                break;
-        }
-        *ret = u;
+	case 7: /* vlong */
+	case 8: /* uvlong */
+		fn(&u, *(Vlong*)lv, rv);
+		*(Vlong*)lv = u;
+		break;
+	}
+	*ret = u;
 }
 
 void
 _p2v(Vlong *ret, void *p)
 {
-        long t;
+	long t;
 
-        t = (ulong)p;
-        ret->lo = t;
-        ret->hi = 0;
+	t = (ulong)p;
+	ret->lo = t;
+	ret->hi = 0;
 }
 
 void
 _sl2v(Vlong *ret, long sl)
 {
-        long t;
+	long t;
 
-        t = sl;
-        ret->lo = t;
-        ret->hi = t >> 31;
+	t = sl;
+	ret->lo = t;
+	ret->hi = t >> 31;
 }
 
 void
 _ul2v(Vlong *ret, ulong ul)
 {
-        long t;
+	long t;
 
-        t = ul;
-        ret->lo = t;
-        ret->hi = 0;
+	t = ul;
+	ret->lo = t;
+	ret->hi = 0;
 }
 
 void
 _si2v(Vlong *ret, int si)
 {
-        long t;
+	long t;
 
-        t = si;
-        ret->lo = t;
-        ret->hi = t >> 31;
+	t = si;
+	ret->lo = t;
+	ret->hi = t >> 31;
 }
 
 void
 _ui2v(Vlong *ret, uint ui)
 {
-        long t;
+	long t;
 
-        t = ui;
-        ret->lo = t;
-        ret->hi = 0;
+	t = ui;
+	ret->lo = t;
+	ret->hi = 0;
 }
 
 void
 _sh2v(Vlong *ret, long sh)
 {
-        long t;
+	long t;
 
-        t = (sh << 16) >> 16;
-        ret->lo = t;
-        ret->hi = t >> 31;
+	t = (sh << 16) >> 16;
+	ret->lo = t;
+	ret->hi = t >> 31;
 }
 
 void
 _uh2v(Vlong *ret, ulong ul)
 {
-        long t;
+	long t;
 
-        t = ul & 0xffff;
-        ret->lo = t;
-        ret->hi = 0;
+	t = ul & 0xffff;
+	ret->lo = t;
+	ret->hi = 0;
 }
 
 void
 _sc2v(Vlong *ret, long uc)
 {
-        long t;
+	long t;
 
-        t = (uc << 24) >> 24;
-        ret->lo = t;
-        ret->hi = t >> 31;
+	t = (uc << 24) >> 24;
+	ret->lo = t;
+	ret->hi = t >> 31;
 }
 
 void
 _uc2v(Vlong *ret, ulong ul)
 {
-        long t;
+	long t;
 
-        t = ul & 0xff;
-        ret->lo = t;
-        ret->hi = 0;
+	t = ul & 0xff;
+	ret->lo = t;
+	ret->hi = 0;
 }
 
 long
 _v2sc(Vlong rv)
 {
-        long t;
+	long t;
 
-        t = rv.lo & 0xff;
-        return (t << 24) >> 24;
+	t = rv.lo & 0xff;
+	return (t << 24) >> 24;
 }
 
 long
 _v2uc(Vlong rv)
 {
 
-        return rv.lo & 0xff;
+	return rv.lo & 0xff;
 }
 
 long
 _v2sh(Vlong rv)
 {
-        long t;
+	long t;
 
-        t = rv.lo & 0xffff;
-        return (t << 16) >> 16;
+	t = rv.lo & 0xffff;
+	return (t << 16) >> 16;
 }
 
 long
 _v2uh(Vlong rv)
 {
 
-        return rv.lo & 0xffff;
+	return rv.lo & 0xffff;
 }
 
 long
 _v2sl(Vlong rv)
 {
 
-        return rv.lo;
+	return rv.lo;
 }
 
 long
 _v2ul(Vlong rv)
 {
 
-        return rv.lo;
+	return rv.lo;
 }
 
 long
 _v2si(Vlong rv)
 {
 
-        return rv.lo;
+	return rv.lo;
 }
 
 long
 _v2ui(Vlong rv)
 {
 
-        return rv.lo;
+	return rv.lo;
 }
 
 int
 _testv(Vlong rv)
 {
-        return rv.lo || rv.hi;
+	return rv.lo || rv.hi;
 }
 
 int
 _eqv(Vlong lv, Vlong rv)
 {
-        return lv.lo == rv.lo && lv.hi == rv.hi;
+	return lv.lo == rv.lo && lv.hi == rv.hi;
 }
 
 int
 _nev(Vlong lv, Vlong rv)
 {
-        return lv.lo != rv.lo || lv.hi != rv.hi;
+	return lv.lo != rv.lo || lv.hi != rv.hi;
 }
 
 int
 _ltv(Vlong lv, Vlong rv)
 {
-        return (long)lv.hi < (long)rv.hi ||
-                (lv.hi == rv.hi && lv.lo < rv.lo);
+	return (long)lv.hi < (long)rv.hi ||
+		(lv.hi == rv.hi && lv.lo < rv.lo);
 }
 
 int
 _lev(Vlong lv, Vlong rv)
 {
-        return (long)lv.hi < (long)rv.hi ||
-                (lv.hi == rv.hi && lv.lo <= rv.lo);
+	return (long)lv.hi < (long)rv.hi ||
+		(lv.hi == rv.hi && lv.lo <= rv.lo);
 }
 
 int
 _gtv(Vlong lv, Vlong rv)
 {
-        return (long)lv.hi > (long)rv.hi ||
-                (lv.hi == rv.hi && lv.lo > rv.lo);
+	return (long)lv.hi > (long)rv.hi ||
+		(lv.hi == rv.hi && lv.lo > rv.lo);
 }
 
 int
 _gev(Vlong lv, Vlong rv)
 {
-        return (long)lv.hi > (long)rv.hi ||
-                (lv.hi == rv.hi && lv.lo >= rv.lo);
+	return (long)lv.hi > (long)rv.hi ||
+		(lv.hi == rv.hi && lv.lo >= rv.lo);
 }
 
 int
 _lov(Vlong lv, Vlong rv)
 {
-        return lv.hi < rv.hi ||
-                (lv.hi == rv.hi && lv.lo < rv.lo);
+	return lv.hi < rv.hi ||
+		(lv.hi == rv.hi && lv.lo < rv.lo);
 }
 
 int
 _lsv(Vlong lv, Vlong rv)
 {
-        return lv.hi < rv.hi ||
-                (lv.hi == rv.hi && lv.lo <= rv.lo);
+	return lv.hi < rv.hi ||
+		(lv.hi == rv.hi && lv.lo <= rv.lo);
 }
 
 int
 _hiv(Vlong lv, Vlong rv)
 {
-        return lv.hi > rv.hi ||
-                (lv.hi == rv.hi && lv.lo > rv.lo);
+	return lv.hi > rv.hi ||
+		(lv.hi == rv.hi && lv.lo > rv.lo);
 }
 
 int
 _hsv(Vlong lv, Vlong rv)
 {
-        return lv.hi > rv.hi ||
-                (lv.hi == rv.hi && lv.lo >= rv.lo);
+	return lv.hi > rv.hi ||
+		(lv.hi == rv.hi && lv.lo >= rv.lo);
 }
diff --git a/src/pkg/syscall/asm_linux_arm.s b/src/pkg/syscall/asm_linux_arm.s
index 830d41c..a579088 100644
--- a/src/pkg/syscall/asm_linux_arm.s
+++ b/src/pkg/syscall/asm_linux_arm.s
@@ -17,9 +17,21 @@
 	MOVW	12(SP), R1
 	MOVW	16(SP), R2
 	SWI		$0
-	MOVW	R0, 20(SP)	// r1
-	MOVW	R1, 24(SP)	// r2
+	MOVW	$0xfffff001, R1
+	CMP		R1, R0
+	BLS		ok
+	MOVW	$-1, R1
+	MOVW	R1, 20(SP)	// r1
+	MOVW	$0, R2
+	MOVW	R2, 24(SP)	// r2
+	RSB		$0, R0, R0
+	MOVW	R0, 28(SP)	// errno
+	BL		runtime·exitsyscall(SB)
+	RET
+ok:
+	MOVW	R0, 20(SP) // r1
 	MOVW	$0, R0
+	MOVW	R0, 24(SP)	// r2
 	MOVW	R0, 28(SP)	// errno
 	BL		runtime·exitsyscall(SB)
 	RET
@@ -36,9 +48,21 @@
 	MOVW	24(SP), R4
 	MOVW	28(SP), R5
 	SWI		$0
-	MOVW	R0, 32(SP)	// r1
-	MOVW	R1, 36(SP)	// r2
+	MOVW	$0xfffff001, R1
+	CMP		R1, R0
+	BLS		ok6
+	MOVW	$-1, R1
+	MOVW	R1, 32(SP)	// r1
+	MOVW	$0, R2
+	MOVW	R2, 36(SP)	// r2
+	RSB		$0, R0, R0
+	MOVW	R0, 40(SP)	// errno
+	BL		runtime·exitsyscall(SB)
+	RET
+ok6:
+	MOVW	R0, 32(SP) // r1
 	MOVW	$0, R0
+	MOVW	R0, 36(SP)	// r2
 	MOVW	R0, 40(SP)	// errno
 	BL		runtime·exitsyscall(SB)
 	RET
@@ -50,8 +74,19 @@
 	MOVW	12(SP), R1
 	MOVW	16(SP), R2
 	SWI		$0
-	MOVW	R0, 20(SP)	// r1
-	MOVW	R1, 24(SP)	// r2
+	MOVW	$0xfffff001, R1
+	CMP		R1, R0
+	BLS		ok1
+	MOVW	$-1, R1
+	MOVW	R1, 20(SP)	// r1
+	MOVW	$0, R2
+	MOVW	R2, 24(SP)	// r2
+	RSB		$0, R0, R0
+	MOVW	R0, 28(SP)	// errno
+	RET
+ok1:
+	MOVW	R0, 20(SP) // r1
 	MOVW	$0, R0
+	MOVW	R0, 24(SP)	// r2
 	MOVW	R0, 28(SP)	// errno
 	RET